pandas之數據結構


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的屬性valuesindex來查看數組及其索引。


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中的isnullnotnull函數用於檢測缺失數據。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組成的字典。

創建

  1. 通過傳入等長列表組成的字典。
  2. 傳入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。

還有其他方法,如:

  1. 類似列表切片,可以看到器索引也是從0開始。
  2. 按照指定的索引選擇一行或多行,使用函數.loc[]
  3. 指定位置來選擇一行或多行,使用.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 計算索引的唯一值數組


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM