pandas的數據結構介紹

本文目錄概要爲:Series,DataFrame,索引對象。

引用約定:

from pandas import Series,DataFrame
import pandas as pd

因此,只要你在代碼中看到pd,就得想到這是pandas。因爲Series和DataFrame用的次數非常多,所以將其引入本地命名空間會更方便。

要使用pandas,你首先就得熟悉它的兩個主要數據結構:Series和DataFrame。雖然它們並不能解決所有問題,但它們爲大多數應用提供了一種可靠的、易於使用的基礎。

Series

Series是一種類似於一維數組的對象,它由一組數據(各種Numpy數據類型)以及一組與之相關的數據標籤(即索引)組成。僅由一組數據即可產生最簡單的Series

>>> obj=Series([4,7,-5,3])
>>> obj
0    4
1    7
2   -5
3    3
dtype: int64

Series的字符串表現形式爲:索引在左邊,值在右邊。由於我們沒有爲數據指定索引,於是會自動創建一個0到N-1(N爲數據的長度)的整數型索引。你可以通過Series的values和index屬性獲取其數組表示形式和索引對象:

>>> obj.values
array([ 4,  7, -5,  3])
>>> obj.index
RangeIndex(start=0, stop=4, step=1)

通常,我們希望所創建的Series帶有一個可以對各個數據點進行標記的索引

>>> obj2=Series([4,7,-5,3],index=['d','b','a','c'])
>>> obj2
d    4
b    7
a   -5
c    3
dtype: int64
>>> obj2.index
Index(['d', 'b', 'a', 'c'], dtype='object')

Series對象本身及其索引都有一個name屬性,該屬性跟pandas其他的關鍵功能關係非常密切。
Series的索引也可以通過賦值的方式就地修改:

>>> obj2.name='obj2Name'
>>> obj2.index=['one','two','three','four']
>>> obj2.index.name='obj2IndexName'
>>> obj2
obj2IndexName
one      4
two      7
three   -5
four     3
Name: obj2Name, dtype: int64

與普通的Numpy數組相比,你可以通過索引的方式選取Series中的單個或一組值

Numpy數組運算(如根據布爾型數組進行過濾、標量乘法、應用數學函數等)都會保留索引和值之間的鏈接。
>>> obj2['one']
4
>>> obj2[['two','one']]
obj2IndexName
two    7
one    4
Name: obj2Name, dtype: int64
>>> obj2[['two','one']]=6
>>> obj2
obj2IndexName
one      6
two      6
three   -5
four     3
Name: obj2Name, dtype: int64

還可以將Series看做是一個定長的有序字典,因爲它是索引值到數據值的一個映射。它可以用在許多原本需要字典參數的函數

>>> 'one' in obj2
True

如果數據被存放在一個Python字典中,也可以直接通過這個字典來創建Series
傳入字典,則結果Series的索引就是原字典的鍵(有序排列)

>>> sdata={'Ohio':35000,'Texas':72000,'Oregon':16000,'Utah':5000}
>>> obj3=Series(sdata)
>>> obj3
Ohio      35000
Oregon    16000
Texas     72000
Utah       5000
dtype: int64

如果索引列所對應的數據找不到,其結果就爲NaN(即“非數字”not a number,在pandas中,它用於表示缺失或NA值 not available)。

>>> states=['California','Ohio','Oregon','Texas']
>>> obj4=Series(sdata,index=states)
>>> obj4
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         72000.0
dtype: float64

pandas的isnull和notnull函數可用於檢測缺失數據:

>>> obj4.isnull()
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool
>>> pd.notnull(obj4)
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

對於許多應用而言,Series最重要的一個功能是:它在算術運算中會自動對齊不同索引的數據

>>> obj3
Ohio      35000
Oregon    16000
Texas     72000
Utah       5000
dtype: int64
>>> obj4
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         72000.0
dtype: float64
>>> obj3+obj4
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         144000.0
Utah               NaN
dtype: float64

DataFrame

DataFrame是一個表格型的數據結構,它含有一組有序的列,每列可以是不同的值類型(數值、字符串、布爾值等)。DataFrame既有行索引也有列索引,它可以被看做由Series組成的字典(共用同一個索引)。跟其他類似的數據結構相比(如R的data.frame),DataFrame中面向行和麪向列的操作基本上是平衡的。其實,DataFrame中的數據是以一個或多個二維塊存放的(而不是列表、字典或別的一維數據結構)。

雖然DataFrame是以二維結構保存數據的,但你仍然可以輕鬆地將其表示爲更高維度的數據(層次化索引的表格型結構,這是pandas中許多高級數據處理功能的關鍵要素)。

構建DataFrame的方式很多,最常用的一種是直接傳入一個由等長列表或Numpy數組組成的字典,結果DataFrame會自動加上索引(跟Series一樣),且全部列會被有序排列:

>>> data={'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
...       'year':[2000,2001,2002,2001,2002],
...       'pop':[1.5,1.7,3.6,2.4,2.9]}
>>> frame=DataFrame(data)
>>> frame
   pop   state  year
0  1.5    Ohio  2000
1  1.7    Ohio  2001
2  3.6    Ohio  2002
3  2.4  Nevada  2001
4  2.9  Nevada  2002

如果指定了列序列,則DataFrame的列就會按照指定順序進行排列:

>>> DataFrame(data,columns=['year','state','pop'])
   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9

跟Series一樣,如果傳入的列在數據中找不到,就會產生NA值:

>>> frame2=DataFrame(data,columns=['year','state','pop','debt'],
...                  index=['one','two','three','four','five'])
>>> frame2
       year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
>>> frame2.columns
Index(['year', 'state', 'pop', 'debt'], dtype='object')
>>> frame2.index
Index(['one', 'two', 'three', 'four', 'five'], dtype='object')

通過類似字典標記的方式或屬性的方式,可以將DataFrame的列獲取爲一個Series。返回的Series擁有原DataFrame相同的索引,且其name屬性也已經被相應的設置好了:


也可以通過位置或名稱的方式進行獲取,比如用索引字段ix


可以通過賦值的方式進行修改。例如,我們可以給那個空的“debt”列賦上一個標量值或一組值:

>>> frame2.debt=16.5
>>> frame2
       year   state  pop  debt
one    2000    Ohio  1.5  16.5
two    2001    Ohio  1.7  16.5
three  2002    Ohio  3.6  16.5
four   2001  Nevada  2.4  16.5
five   2002  Nevada  2.9  16.5
>>> import numpy as np
>>> frame2['debt']=np.arange(5.)
>>> frame2
       year   state  pop  debt
one    2000    Ohio  1.5   0.0
two    2001    Ohio  1.7   1.0
three  2002    Ohio  3.6   2.0
four   2001  Nevada  2.4   3.0
five   2002  Nevada  2.9   4.0

列表或數組賦值給某個列時,其長度必須跟DataFrame的長度相匹配。如果賦值的是一個Series,就會精確匹配DataFrame的索引,所有的空位都將被填上缺失值


不存在的列賦值會創建出一個新列。關鍵字del用於刪除列:

>>> frame2['eastern']=frame2.state=='Ohio'
>>> frame2
       year   state  pop  debt  eastern
one    2000    Ohio  1.5   NaN     True
two    2001    Ohio  1.7  -1.2     True
three  2002    Ohio  3.6   NaN     True
four   2001  Nevada  2.4  -1.5    False
five   2002  Nevada  2.9  -1.7    False
>>> del frame2['eastern']
>>> frame2.columns
Index(['year', 'state', 'pop', 'debt'], dtype='object')

警告:通過索引方式返回的列只是相應數據的視圖而已,並不是副本。因此,對返回的Series所做的任何就地修改全都會反映到源DataFrame上。通過Series的copy方法即可顯示的複製列

另一種常見的數據形式是嵌套字典(也就是字典的字典)。如果將它傳給DataFrame,他就會被解釋爲:外層字典的鍵作爲列內層鍵作爲行索引:內層字典的鍵會被合併、排序以形成最終的索引。

>>> pop={'Nevada':{2001:2.4,2002:2.9},
... 'Ohio':{2000:1.5,2001:1.7,2002:3.6}}
>>> frame3=DataFrame(pop)
>>> frame3
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7
2002     2.9   3.6

當然,你也可以對該結果進行轉置

>>> frame3T=frame3.T
>>> frame3T.columns
Int64Index([2000, 2001, 2002], dtype='int64')

如果顯示指定了索引,則會進行數據對齊:

>>> DataFrame(pop,index=[2001,2002,2003])
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2003     NaN   NaN

Series組成的字典也差不多一樣的用法:

>>> pdata={'Ohio':frame3['Ohio'][:-1],'Nevada':frame3['Nevada'][0:2]}
>>> DataFrame(pdata)
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7

如果設置了DataFrame的index和columns的name屬性,這些信息會被顯示出來。跟Series一樣,values屬性也會以二維ndarray的形式返回DataFrame中的數據:

>>> frame3.index.name='year'
>>> frame3.columns.name='state'
>>> frame3
state  Nevada  Ohio
year               
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6
>>> frame3.values
array([[nan, 1.5],
       [2.4, 1.7],
       [2.9, 3.6]])

下表列出可以輸入給DataFrame構造器的數據:

二維ndarray
由數組、列表或元組組成的字典
Numpy結構化、記錄數組
由Series組成的字典
由字典組成的字典
字典或Series的列表
由列表或元組組成的列表
另一個DataFrame
Numpy的MaskedArray

索引對象

pandas的索引對象負責管理軸標籤和其他元數據(比如軸名稱等)。構建Series或DataFrame時,所用到的任何數組或其他序列的標籤都會被轉換成一個Index:

>>> obj=Series(range(3),index=['a','b','c'])
>>> index=obj.index
>>> index
Index(['a', 'b', 'c'], dtype='object')
>>> index[1:]
Index(['b', 'c'], dtype='object')

Index對象是不可修改的(immutable),因此用戶不能對其進行修改。不可修改性非常重要,這使Index對象在多個數據結構之間安全共享。

>>> index[1]='d'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py", line 1724, in __setitem__
    raise TypeError("Index does not support mutable operations")
TypeError: Index does not support mutable operations

雖然大部分用戶都不需要知道太多關於Index對象的細節,但它們確實是pandas數據模型的重要組成部分。

下表列出了pandas中內置的Index類。由於開發人員的不懈努力,Index甚至可以被繼承從而實現特別的軸索引功能。

Index最泛化的Index對象,將軸標籤表示爲一個由Python對象組成的Numpy數組
Int64Index針對整數的特殊Index
MultiIndex“層次化”索引對象,表示單個軸上的多層索引。可以看做由元組組成的數組
DatetimeIndex存儲納秒級時間戳(用Numpy的datetime64類型表示)
PeriodIndex針對Period數據(時間間隔)的特殊Index

除了長得像數組,Index的功能也類似一個固定大小的集合。

>>> frame3
state  Nevada  Ohio
year               
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6
>>> 'Ohio' in frame3.columns
True
>>> 2003 in frame3.index
False

每個索引都有一些方法和屬性,它們可用於設置邏輯並回答有關該索引所包含的數據的常見問題。下表列出了Index的方法和屬性

append連接另一個Index對象,產生一個新的Index
diff計算差集,並得到一個Index
intersection計算交集
union計算並集
isin計算一個指示各值是否都包含在參數集合中的布爾型數組
delete刪除索引i處的元素,並得到新的Index
drop刪除傳入的值,並得到新的Index
insert將元素插入到索引i處,並得到新的Index
is_monotonic當各元素均大於等於前一個元素時,返回True
is_unique當Index沒有重複值時,返回True
unique計算Index中唯一值的數組

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章