python 二维数组长度_谈一谈多维数组
談
一
談
多
維
數
組
在各種語言中,都提供了多維數組。而多維數組又是很讓人迷惑的一個語法結構。今天給大家聊一下多維數組使用中的一些問題。
這里,以Python和IDL為主講解。
多維數組的概念
首先說說多維數組的概念。多維數組在不同語言中有大同小異的語法定義,但是邏輯定義上基本上一致,就是同數據類型、同邏輯含義的數據單元構成的能夠用整數為坐標訪問的超立方體的數據集合。
這里我用的“超立方體”,指的是數據可以表達為多個維度的下標,例如線段、矩形、立方體……它們的反例就是所謂的“參差數組”,比如下面這樣的:
1, 2, 3, 4, 5
6, 7, 8
9, 1, 2, 3
這就是典型的一個參差數組,某一個維度的下標范圍受到另外的維度的下標取值影響。而超立方體呢,每個維度的下標取值范圍(寬度)是固定的。這個情況在python的列表嵌套、C語言動態分配實現的多維數組中都會遇到。在某些特殊情況下確實有用,但是不在這里規范化的數組討論范圍內。
第二個特點,同數據類型。正常情況下的數組都是由同類數據構成的,但是也有例外,如python的列表(list)、元組(tuple)、字典(dict),javascript中的數組,這些都是允許元素類型隨意的。這種情況往往出現在腳本語言中,充分體現了語言的靈活性,但是這個真不是數組,后面會談到。
第三個特點,同數據含義。同樣的數據類型,不代表含義就相同,這個是做科學的人編程經常犯的一個毛病。典型案例就是記錄數組。例如表達光譜,做一個3×n的數組,其中第一行代表波長,第二行代表流量,第三行代表誤差……從語法上來說,這沒錯,很多光譜也是這么發布的,但是從邏輯含義上來說,我更愿意把這個東西看做3個一維數組的強行拼湊,只是因為他們的數據類型都是浮點數而已。
多維數組 VS 記錄表
上面提到的最后一個情況,有些叫做二維表,我更愿意叫做記錄表,以區別于二維數組。除了上面的光譜,我再舉個例子:
RA | Dec | Mag_V |
06:54:15.29 | +56:52:09.4 | 16.65 |
22:09:38.91 | -03:51:48.1 | 13.25 |
這是天文上很常見的一張記錄表。這個表中,列數是固定的,每一列的含義也是獨立的、固定的,但是行是可以擴展的。在numpy中,這種數據用記錄(record)數組來表達,而IDL則使用結構體(structure)數組。在各種語言中基本上也都是用記錄、結構體、類/對象等等來表達的。在關系型數據庫中,這就是一個表。
記錄表和二維數組的相似性,有這么幾點:
① 都可以看做是二維的,有些語言中也確實當做二維數組訪問;
② 如果各列的數據類型剛好一致(或者可以升級到相同類型),那么也可以用二維數組來裝;
但是它們有本質的區別:
1,二維數組的下標之間是等價的,例如表示一幅圖像時是x,y,表達矩陣是行列,可以轉置、翻轉,不影響其性質;而記錄表的行一般表達記錄,而列往往為字段,二者不可互換。
2,二維數組的大小形狀和數據來源有關,是一起提供的;而記錄表的列(字段)來源和行(記錄)的來源是不同的。
3,二維數組不同維度的下標都是整數(或者是切片),而記錄表的行是整數或切片下標,列是字段名來訪問。
4,二維數組在語法上是二維的,而記錄表在大部分語言的語法中,是類型為記錄的一維數組。
多維數組 VS 數組的數組
這是一個很奇怪的命題……但是在許多語言的語法中確實是這樣的。典型的例子:C語言。
二者從語法上來看,區別就是:前者是a[1,2],后者是a[1][2]。
出現后者的原因,主要是看語法本身的支持程度了。對于后者,有些時候是語法限制下表達多維數組的某種辦法而已。例如在python中,用list或者tuple來表達多維數組的時候就是這樣的。
在各種語言中,表達多維數組常數的時候,往往使用的也是數組的數組的表達方式。例如:
[ [1,2,3,4], [5,6,7,8], [9,10,11,12] ]
這實際上就是一個由3個長度為4的一維數組組成的一個“數組的數組”,但是實際表達的是3x4的二維數組。
對于數組的數組,大家要注意的就是別變成參差數組。當然參差數組也并不是壞事,它的最大特點是節約內存,例如,字符串數組,實際上就是參差數組……
還是要提一下python,它本身是不提供數組的,list/tuple都是所謂的動態數據結構。而真正的數組是通過numpy.ndarray來提供的,內部本質是面向對象加運算符重載,不過對于大家來說當做多維數組用就是了。
多維數組的存儲
對于多維數組來說,邏輯上的概念中是多維的,而實際上計算機內存大家都知道是線性的,磁盤文件存儲拋開柱面、磁道、扇區等等物理概念,邏輯上也是線性的。那么這二者是怎么協調的呢?
這時候,多維數組實際上被“攤平”了,變形成一維數組進行存放。這個情況下有兩種方法來攤平,一種是行優先,一種是列優先,或者換句話說就是下標從左到右攤平還是從右到左。
可能聽得有點暈,不過不要緊,大家只要記得會攤平就行了。不過不要以為這個操作對咱們處理數據沒影響,實際上有的。舉兩個常見的例子:
IDL的where函數,大家基本上都用過。這個函數返回的是滿足條件的元素的下標(實際上就是參數中為1的元素下標)。這時候返回的下標,就是原數組攤平之后的下標,是一維的。相對來說,np.where返回的,則是原始的下標。
在IDL中,除了多維下標的方式訪問數據,也可以直接使用攤平后的一維下標來訪問數據。這在各種編程語言中都是比較特殊的。
另外一個例子,如果大家在matplotlib中畫直方圖(hist),畫的是一個二維數組的原始的分布圖,就會發現很尷尬的一件事,m*n的數組,它給你畫n個直方圖疊在一起……因為它對每一行都去畫了一個直方圖。這個時候,我們就需要主動把數組攤平:plt.hist(a.flatten()),這樣就把整個數組單獨拿來畫圖了。當然用reshape也可以。
除了這兩個地方不同,還有一個地方可能大家編程的時候都會被提醒的:在astropy讀入的fits圖像中,要選擇某個像元,必須是a[y,x]。這其實也是因為數據的內部行、列優先不同造成的。
多維數組的統計
最后說一下,多維數組的統計的事情。假如有數組a,是m*n*k的,那么我們可以求出以下一系列均值:
python:
m = np.mean(a):求出全部元素的均值,是一個值
m = np.mean(a, axis=0):對第0維求均值,m是n*k的二維數組,m[i, j]是mean(a[:, i, j])
m = np.mean(a, axis=(1,2)),對第1、2維求均值,m是長為m的一維數組,m[i]是mean(a[i, :, :])
上面的例子中,選取的是前面或者后面的維度進行統計,實際上維度是可以任意組合的。
IDL也類似:
m = mean(a):求全部元素平均值。
m = mean(a, dim=1):對第1維求均值,m是n*k的數組。注意:盡管IDL的下標是從0開始的,但是在表達維度的時候,是從1開始的。其實內在原因是,dim=0的話,這個參數就會被默認當做沒有賦值……
至于上面的最后那個寫法,IDL不支持……
好了,就這么多了……我實在憋不出別的東西來了。有啥問題,下期再見
歡迎關注“小林在線”
一個可能有點看不懂的公號
總結
以上是生活随笔為你收集整理的python 二维数组长度_谈一谈多维数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何用PPT编制方案 (2)PPT
- 下一篇: websocket python爬虫_p