pandas數據結構
這里需要謹記兩點
pandas是基於numpy構建的。
pandas的數據結構實際上和Excel是一致的。
為什么這樣說第二點呢?
因為在我看來,它的數據結構可以這樣理解。
Series就相當於Excel的一列,有對應的行號。
DataFrame就相當於Excel表格,有行,有列,每一列還可以是不同的數據類型。
索引對象,就是這些行號,列號,以及Excel中絕對引用與相對引用。
如果按照上面這樣想,就很容易理解了。
Series
創建
Series有一組數據(各種numpy數據類型)以及與之相關的數據標簽(索引組成)。
就相當於Excel中的一列以及對應的行號。
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: from pandas import Series,DataFrame
In [4]: ser = Series([-2,-4,3,-1,5])
In [5]: ser
Out[5]:
0 -2
1 -4
2 3
3 -1
4 5
dtype: int64
可以看到,Series與Excel的表格中的某列,極其相似,索引在左,值在右。
這里的0,1,...4是Series自動創建的索引。
這也說明,如果我們不指定索引,那么Series會自動為數據值創建一個0-(N-1)(N為數據長度)的整數型索引。
不過,Series支持我們指定索引,通過index參數。
In [7]: ser2 = Series([-2,-4,3,-1,5],index=['d','a','c','b','e'])
In [8]: ser2
Out[8]:
d -2
a -4
c 3
b -1
e 5
dtype: int64
我們可以通過Series的屬性values和index來查看數組及其索引。
In [9]: ser2.values#查看數組形式
Out[9]: array([-2, -4, 3, -1, 5], dtype=int64)
In [10]: ser2.index#查看索引
Out[10]: Index(['d', 'a', 'c', 'b', 'e'], dtype='object')
賦值
還可通過索引賦值,取值,賦給不存在的索引值會添加一個新值。
In [11]: ser2['c'] #取單值
Out[11]: 3
In [12]: ser2['b'] = 12#賦值
In [13]: ser2
Out[13]:
d -2
a -4
c 3
b 12
e 5
dtype: int64
In [14]: ser2['f'] = 10 #添加新值
In [16]: ser2[['c','b','f','a']] #取出一組值
Out[16]:
c 3
b 12
f 10
a -4
dtype: int64
我們還可以復制的方式來更改索引
In [43]: ser.index = ['one','two','three','four','five']
In [44]: ser
Out[44]:
one -2
two -4
three 3
four -1
five 5
dtype: int64
字典創建
其實,正常的想法應該是將Series看做一個有序字典,因為很顯然通過上面的實驗我們可以發現,它也是索引值到數據值的映射。因此它可以用在字典函數中。
In [17]: 'b' in ser2
Out[17]: True
In [18]: 'g' in ser2
Out[18]: False
故,可以用字典來創建Series。
In [19]: zidian = {'nihao':2000,'wobuhao':2300,'hahah':3020,'niqu':4300}#字典
In [20]: ser3 = Series(zidian)#創建Series
In [21]: ser3
Out[21]:
hahah 3020
nihao 2000
niqu 4300
wobuhao 2300
dtype: int64
可以注意到
字典的鍵就是Series中的索引,而且還會有序排列。
In [29]: suoyin = ['jiushi','nihao','niqu','wobuhao']
In [30]: ser4 = Series(zidian,index = suoyin)
In [31]: ser4
Out[31]:
jiushi NaN
nihao 2000.0
niqu 4300.0
wobuhao 2300.0
dtype: float64
在上面這個實驗中可以發現,
我們指定了索引,zidian中與suoyin相匹配的值被取了出來,而jiushi沒有值,匹配不到,因此結果為NaN。
NaN(not a number)非數字,它表示缺失或NA值
缺失(mising)或NA表示缺失數據。
pandas中的isnull和notnull函數用於檢測缺失數據。Series也有類似的示例方法。
In [32]: pd.isnull(ser4)
Out[32]:
jiushi True
nihao False
niqu False
wobuhao False
dtype: bool
In [33]: pd.notnull(ser4)
Out[33]:
jiushi False
nihao True
niqu True
wobuhao True
dtype: bool
In [34]: ser4.isnull()
Out[34]:
jiushi True
nihao False
niqu False
wobuhao False
dtype: bool
In [35]: ser4.notnull()
Out[35]:
jiushi False
nihao True
niqu True
wobuhao True
dtype: bool
置於缺失數據怎樣處理,我們以后在討論。
數組運算
numpy的數組運算都可以應用到Series。
In [26]: ser[ser > 0] # 布爾數組過濾
Out[26]:
2 3
4 5
dtype: int64
In [27]: ser * 2 #標量運算
Out[27]:
0 -4
1 -8
2 6
3 -2
4 10
dtype: int64
In [28]: np.exp(ser) # 應用數學函數
Out[28]:
0 0.135335
1 0.018316
2 20.085537
3 0.367879
4 148.413159
dtype: float64
In [36]: ser3
Out[36]:
hahah 3020
nihao 2000
niqu 4300
wobuhao 2300
dtype: int64
In [37]: ser4
Out[37]:
jiushi NaN
nihao 2000.0
niqu 4300.0
wobuhao 2300.0
dtype: float64
In [38]: ser3 + ser4 #兩個Series相加
Out[38]:
hahah NaN
jiushi NaN
nihao 4000.0
niqu 8600.0
wobuhao 4600.0
dtype: float64
可以注意到:
索引與值之間的連接一直被保留
值會變,索引不會變
聯想下Excel,不論做什么運算,行號是不會變得。
兩個Series相加也類似於Excel中的合並計算。
Series對象本身和索引還有一個name屬性。
In [39]: ser4.naem = 'test'#name屬性
In [40]: ser4.index.name = 'number'#name屬性
In [41]: ser4
Out[41]:
number
jiushi NaN
nihao 2000.0
niqu 4300.0
wobuhao 2300.0
dtype: float64
ser2.name = 'test'
ser2.index.naem = 'pop'
ser2
Out[10]:
d -2
a -4
c 3
b -1
e 5
Name: test, dtype: int64
DataFrame
DataFrame就是一個表個性的數據結構,它基本和Excel是一樣的。有行索引(行號),列索引(列號)。
它對行和列的操作基本一致。
也可以看成由Series組成的字典。
創建
- 通過傳入等長列表組成的字典。
- 傳入numpy數組組成的字典。
In [3]: data = {'date':[2015,2012,2000,2013,2016],'city':['haerbin','beijing','tianjin','shijiazhuang','jinan'],'shuju':[1.2,1.3,1.4,2.3,2.7]}#等長列表字典
In [4]: frame = DataFrame(data)
In [5]: frame
Out[5]:
city date shuju
0 haerbin 2015 1.2
1 beijing 2012 1.3
2 tianjin 2000 1.4
3 shijiazhuang 2013 2.3
4 jinan 2016 2.7
In [6]: frame1 = DataFrame(np.random.randn(16).reshape(4,4))#numpy數組
In [7]: frame1
Out[7]:
0 1 2 3
0 -0.077134 0.983138 -0.483991 -1.107506
1 -1.721202 0.057802 0.090921 0.411377
2 -1.973126 1.335374 -0.524562 0.017366
3 -0.311434 1.819138 -0.258790 -0.663582
可以注意到,DataFrame會像Series一樣自動的加上索引,且全部列會被有序排列。
我們也可以指定列的順序(行也是適用的)。
In [8]: DataFrame(data,columns=['date','city','shuju'])
Out[8]:
date city shuju
0 2015 haerbin 1.2
1 2012 beijing 1.3
2 2000 tianjin 1.4
3 2013 shijiazhuang 2.3
4 2016 jinan 2.7
與Series一樣,如果,我們指定的列在數據中不存在,也會產生NA值。
這就相當於,有列名,但是沒有對應的值。
In [12]: frame2 = DataFrame(data,columns=['date','city','shuju','nohere'],index = ['one','two','three','four','five'])
In [13]: frame2
Out[13]:
date city shuju nohere
one 2015 haerbin 1.2 NaN
two 2012 beijing 1.3 NaN
three 2000 tianjin 1.4 NaN
four 2013 shijiazhuang 2.3 NaN
five 2016 jinan 2.7 NaN
In [14]: frame2.columns
Out[14]: Index(['date', 'city', 'shuju', 'nohere'], dtype='object')
但是,指定了six行的話就會返回錯誤,因為數據比我們的行少。
索引
我們可以通過字典或者屬性的方式來獲得一個Series。
列索引
In [15]: frame2['city'] #字典方式
Out[15]:
one haerbin
two beijing
three tianjin
four shijiazhuang
five jinan
Name: city, dtype: object
In [16]: frame2.city #屬性方式
Out[16]:
one haerbin
two beijing
three tianjin
four shijiazhuang
five jinan
Name: city, dtype: object
In [27]: frame2[['date','shuju']]#兩列
Out[27]:
date shuju
one 2015 1.2
two 2012 1.3
three 2000 1.4
four 2013 2.3
five 2016 2.7
In [28]: frame2[[0,1,2]]#索引號
Out[28]:
date city shuju
one 2015 haerbin 1.2
two 2012 beijing 1.3
three 2000 tianjin 1.4
four 2013 shijiazhuang 2.3
five 2016 jinan 2.7
In [29]: frame2[[1:2]]#切片
File "<ipython-input-29-756d0bb4bbed>", line 1
frame2[[1:2]]
^
SyntaxError: invalid syntax
通過以上代碼,我們可以知道DataFrame與Series的索引是相同的。這樣獲取Series的話,其name屬性也被設置好了。
另外,發現DataFrame的列也是存在索引號的。
切片的方法也是行不通的,會返回錯誤
行索引
至於行的獲取我們可以通過位置或者名稱的方式。如索引字段ix。
還有其他方法,如:
- 類似列表切片,可以看到器索引也是從0開始。
- 按照指定的索引選擇一行或多行,使用函數
.loc[]。 - 指定位置來選擇一行或多行,使用
.ioc[]。
In [18]: frame2.ix['three']
Out[18]:
date 2000
city tianjin
shuju 1.4
nohere NaN
Name: three, dtype: object
#此文,不是同一天寫的
In [6]: frame2[0:2]#類似於列表切片
Out[6]:
date city shuju nohere
one 2015 haerbin 1.2 NaN
two 2012 beijing 1.3 NaN
In [12]: frame2[:-2]#類似於列表切片
Out[12]:
date city shuju nohere
one 2015 haerbin 1.2 NaN
two 2012 beijing 1.3 NaN
three 2000 tianjin 1.4 NaN
In [13]: frame2[-4:-2]#類似於列表切片
Out[13]:
date city shuju nohere
two 2012 beijing 1.3 NaN
three 2000 tianjin 1.4 NaN
In [18]: frame2.loc['one']#.loc來選定一行
Out[18]:
date 2015
city haerbin
shuju 1.2
nohere NaN
Name: one, dtype: object
In [20]: frame2.loc['one':'three']#.loc選定多行
Out[20]:
date city shuju nohere
one 2015 haerbin 1.2 NaN
two 2012 beijing 1.3 NaN
three 2000 tianjin 1.4 NaN
可以發現,行索引是可以進行切片的,列是不可以的,具體的索引方法使用,這里就不仔細研究了,因為這里不是重點。
列賦值
可以直接給列進行賦值,這里需要用到索引。
In [35]: frame2['nowhere'] = 1.5
In [36]: frame2
Out[36]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 1.5
two 2012 beijing 1.3 NaN 1.5
three 2000 tianjin 1.4 NaN 1.5
four 2013 shijiazhuang 2.3 NaN 1.5
five 2016 jinan 2.7 NaN 1.5
In [37]: frame2.nowhere = 2
In [38]: frame2
Out[38]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 2
two 2012 beijing 1.3 NaN 2
three 2000 tianjin 1.4 NaN 2
four 2013 shijiazhuang 2.3 NaN 2
five 2016 jinan 2.7 NaN 2
In [39]: frame2['nowhere'] = np.arange(5.0)
In [40]: frame2
Out[40]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 0.0
two 2012 beijing 1.3 NaN 1.0
three 2000 tianjin 1.4 NaN 2.0
four 2013 shijiazhuang 2.3 NaN 3.0
five 2016 jinan 2.7 NaN 4.0
In [41]: frame2.nowhere = np.arange(5.0,10.0)
In [42]: frame2
Out[42]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 5.0
two 2012 beijing 1.3 NaN 6.0
three 2000 tianjin 1.4 NaN 7.0
four 2013 shijiazhuang 2.3 NaN 8.0
five 2016 jinan 2.7 NaN 9.0
In [43]: frame2.nowhere = [1,2,3,4,5,6]
ValueError: Length of values does not match length of index
將列表或數組賦值給某列時,其長度必須與DataFrame的列的長度匹配,如果將Series賦值給DataFrame,則其會與DataFrame的索引精確匹配,如果有空位,則空位是缺失值。
In [44]: x = Series([12, 1.7, 1.9],index = ['one','four','three'])#Sereies
In [45]: frame2.nowhere = x #將Series賦值給frame2的nowhere
In [46]: frame2
Out[46]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 12.0
two 2012 beijing 1.3 NaN NaN
three 2000 tianjin 1.4 NaN 1.9
four 2013 shijiazhuang 2.3 NaN 1.7
five 2016 jinan 2.7 NaN NaN
為不存在的列賦值,會創建這個不存在的列。del是關鍵字,他可以用來刪除列
In [53]: frame2['wu'] = frame2.city == 'tianjin'
In [54]: frame2
Out[54]:
date city shuju nohere nowhere wu
one 2015 haerbin 1.2 NaN 12.0 False
two 2012 beijing 1.3 NaN NaN False
three 2000 tianjin 1.4 NaN 1.9 True
four 2013 shijiazhuang 2.3 NaN 1.7 False
five 2016 jinan 2.7 NaN NaN False
In [57]: del frame2['wu']#刪除列
In [58]: frame2
Out[58]:
date city shuju nohere nowhere
one 2015 haerbin 1.2 NaN 12.0
two 2012 beijing 1.3 NaN NaN
three 2000 tianjin 1.4 NaN 1.9
four 2013 shijiazhuang 2.3 NaN 1.7
five 2016 jinan 2.7 NaN NaN
In [59]: frame2.columns#查看列
Out[59]: Index(['date', 'city', 'shuju', 'nohere', 'nowhere'], dtype='object')
經過試驗,發現在這里使用frame2.wu的索引方式結果不變,也就是說這種方法在這里行不通,因此,最好使用上方代碼塊的方式。
我們還需要知道的是,對與索引所返回的Series所做的任何更改都會反映到DataFrame上面。
DataFrame還可以接受嵌套字典,也就是字典的字典。外層字典的鍵作為列,內層鍵則作為行的索引。
屬性
我們可以設置DataFrame的index和columns屬性,也就是行和列的屬性。
In [60]: frame2.index.name = 'year'
In [61]: frame2.columns.name = 'state'
In [62]: frame2
Out[62]:
state date city shuju nohere nowhere
year
one 2015 haerbin 1.2 NaN 12.0
two 2012 beijing 1.3 NaN NaN
three 2000 tianjin 1.4 NaN 1.9
four 2013 shijiazhuang 2.3 NaN 1.7
five 2016 jinan 2.7 NaN NaN
DataFrame的values屬性與Series一樣,都會以二維數組形式返回。
In [63]: frame2.values
Out[63]:
array([[2015, 'haerbin', 1.2, nan, 12.0],
[2012, 'beijing', 1.3, nan, nan],
[2000, 'tianjin', 1.4, nan, 1.9],
[2013, 'shijiazhuang', 2.3, nan, 1.7],
[2016, 'jinan', 2.7, nan, nan]], dtype=object)
可以看到dtype的類型是object,這是因為其各列的數據類型不同,因此返回了一個可以兼容所有列的數值類型。
索引
上方我們已經說了很久的索引對象,索引對象最大的特點是不可修改性(immutable)。
In [64]: inde = frame2.index
In [65]: inde
Out[65]: Index(['one', 'two', 'three', 'four', 'five'], dtype='object', name='year')
In [66]: inde[1]
Out[66]: 'two'
In [67]: inde[1] = 'hah'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-67-79c2a592e832> in <module>()
----> 1 inde[1] = 'hah'
D:\Users\sunshine\Anaconda\lib\site-packages\pandas\indexes\base.py in __setitem__(self, key, value)
1402
1403 def __setitem__(self, key, value):
-> 1404 raise TypeError("Index does not support mutable operations")
1405
1406 def __getitem__(self, key):
TypeError: Index does not support mutable operations
判斷某一行或者某一列是否在索引中。
In [70]: 'city' in frame2.columns
Out[70]: True
In [71]: 'three' in frame2.index
Out[71]: True
除此之外,index還存在很多方法和屬性。
| 索引方法和屬性 | 說明 |
|---|---|
| append | 鏈接額外的索引對象,產生一個新的索引 |
| diff | 計算索引的差集 |
| intersection | 計算交集 |
| union | 計算並集 |
| isin | 計算出一個布爾數組表示每一個值是否包含在所傳遞的集合里 |
| delete | 計算刪除位置i的元素的索引 |
| drop | 計算刪除所傳遞的值后的索引 |
| insert | 計算在位置i插入元素后的索引 |
| is_monotonic | 返回True,如果每一個元素都比它前面的元素大或相等 |
| is_unique | 返回True,如果索引沒有重復的值 |
| unique | 計算索引的唯一值數組 |
