pandas入門

寫在前面的話

在做天文數據處理的過程中,基本上是和表格數據打交道,因此在處理天文數據的過程中pandas就是自己首選。利用pandas可以很方便的提取出自己想要的行或列的數據,方便自己后面做統(tǒng)計分析。因此,寫一篇pandas入門的文章記錄一下自己學習pandas的總結。

推薦另外一篇pandas入門文檔:10 Minutes to pandas

pandas的功能

  1. 具備按軸自動或顯式數據對齊功能的數據結構。這可以防止許多由于數據未對齊以及來自不同數據源(索引方式不同)的數據而導致的常見錯誤。
  2. 集成時間序列功能。
  3. 既能處理時間序列數據也能處理非時間序列數據的數據結構。
  4. 數學運算和約簡(比如對某個軸求和)可以根據不同的元數據(軸號)執(zhí)行。
  5. 靈活處理缺失數據。
  6. 合并及其他出現在常見數據庫(例如基于SQL的)中的關系型運算。

pandas引入約定

import pandas as pd
from pandas import Series,DataFrame

pandas數據結構介紹

要使用pandas,必須先要熟悉它的兩個主要數據結構:SeriesData Frame。

Series

Series是一種類似于一維數組的對象,它由一組數據和一組與之相關的數據標簽(索引)組成。

由一組數據生產簡單的Series
a = [1,3,'hello',4.5]
b =pd.Series(a)
print(b)
0        1
1        3
2    hello
3      4.5
dtype: object

Series的表現形式為:索引在左邊,值在右邊。由于沒有為數據指定索引,默認自動創(chuàng)建一個0到n-1(n為數據的長度)的整數型索引。可以通過Series的values和index屬性獲取其數組表示形式和索引對象:

b.values
array([1, 3, 'hello', 4.6], dtype=object)
b.index  #like range(4)
RangeIndex(start=0, stop=4, step=1)

通過索引可以獲取對應的值:

b[2]
'hello'
b[1:3]
1        3
2    hello
dtype: object
b[[1,2]]
1        3
2    hello
dtype: object

自定義索引:

a = [1,3,'hello',4.5]
c = pd.Series(a,index=[c,d,m,n])
print(c)
c        1
d        3
m    hello
n      4.6
dtype: object
c['d']
3
c[['m','n']]
m    hello
n      4.6
dtype: object

使用Numpy函數或者Numpy的運算,都會保留索引值的鏈接:

obj =pd.Series([1,5,7,3,2,-3])
print(obj)
0    1
1    5
2    7
3    3
4    2
5   -3
dtype: int64
obj[obj<3]
0    1
4    2
5   -3
dtype: int64
obj + 1
0    2
1    6
2    8
3    4
4    3
5   -2
dtype: int64

可以將Series看成是一個定長的有序字典,因為它是索引值到數據值的一個映射。

print(c)
c        1
d        3
m    hello
n      4.6
dtype: object
'm' in c
True
's' in c
False

如果數據被存放在一個Python字典中,可以直接通過這個字典來創(chuàng)建Series。

data = {'Tom':25,'Jerry':23,'Allon':26,'xiaoming':7}
sdata = Series(data)
sdata
Tom         25
Jerry       23
Allon       26
xiaoming     7
dtype: int64

如果只傳入一個字典,則結果Series中的索引就是原字典中的鍵(Key)。當然你也可以傳入排好序的字典的鍵來改變順序。

name = ['Jerry','xiaoming','Tom','Bob']
obj1 = Series(data,index=name)
print(obj1)
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
dtype: float64

由于'Bob'所對應的值找不到,所以就顯示NAN(not a number),在pandas中NAN用于表示缺失或者NA值。由于'Allon'不在name中,所以它被從結果中除去。
pandas中的isnullnotnull函數可用于檢查缺失的數據:

pd.isnull(obj1)
Jerry       False
xiaoming    False
Tom         False
Bob          True
dtype: bool
#Series也有類似的用法,是指已經導入Series函數
obj1.isnull()
Jerry       False
xiaoming    False
Tom         False
Bob          True
dtype: bool

Series會根據運算的索引自動對齊數據(類似join操作):

obj2 = Series({'a':4,'d':6,'k':8,'f':7})
obj3 = Series({'d':1,'f':3,'a':6,'n':5})
obj2 + obj3
a    10.0
d     7.0
f    10.0
k     NaN
n     NaN
dtype: float64

Series的name屬性,該屬性與pandas其它關鍵功能關系密切:

obj1
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
dtype: float64
obj1.name = 'population'
obj1.index.name = 'name'
print(obj1)
name
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
Name: population, dtype: float64

Series的索引值可以通過賦值方式就地修改:

obj2
a    4
d    6
k    8
f    7
dtype: int64
obj2.index = ['e','f','h','m']
obj2
e    4
f    6
h    8
m    7
dtype: int64

DataFrame

DataFrame是一個表格型的數據結構,它含有一組有序的列,每列可以是不同的值類型(數值、字符串、布爾值等)。DataFrame既有行索引也有列索引。
建DataFrame的辦法有很多,最常用的一種是直接傳入一個由等長列表或Numpy數組組成的字典:

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

我自己常用的構建DataFrame的方法:

f = [8,5,3,7]
m = [15,75,34,52]
fm = pd.DataFrame([f,m])
fm
    0   1   2   3
0   8   5   3   7
1   15  75  34  52

沒有索引(行or列),DataFrame會自動加上(跟Series一樣)。
對于特別大的DataFrame,head函數會選取前五行:

frame.head()
    state   year    pop
0   Ohio    2000    1.5
1   Ohio    2001    1.7
2   Ohio    2002    3.6
3   Nevada  2001    2.4
4   Nevada  2002    2.9

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

pd.DataFrame(data1, columns=['year','pop','state'])
    year    pop state
0   2000    1.5 Ohio
1   2001    1.7 Ohio
2   2002    3.6 Ohio
3   2001    2.4 Nevada
4   2002    2.9 Nevada
5   2003    3.2 Nevada

通過類似字典標記的方式或屬性的方式,可以將DataFrame的某一列獲取為一個Series:

frame['pop']
0    1.5
1    1.7
2    3.6
3    2.4
4    2.9
5    3.2
Name: pop, dtype: float64
frame.year
0    2000
1    2001
2    2002
3    2001
4    2002
5    2003
Name: year, dtype: int64

提示:返回的Series擁有原DataFrame相同的索引,而且name屬性也被相應的設置好了。

行也可以通過位置或者名稱進行獲取,比如用loc屬性

frame
   state    year    pop
0   Ohio    2000    1.5
1   Ohio    2001    1.7
2   Ohio    2002    3.6
3   Nevada  2001    2.4
4   Nevada  2002    2.9
5   Nevada  2003    3.2
frame.loc[0]
state    Ohio
year     2000
pop       1.5
Name: 0, dtype: object

列可以通過賦值的方式進行修改:

frame['pop'] = 2.0
frame
    state   year    pop
0   Ohio    2000    2.0
1   Ohio    2001    2.0
2   Ohio    2002    2.0
3   Nevada  2001    2.0
4   Nevada  2002    2.0
5   Nevada  2003    2.0

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

#此例是直接添加某一列,當pop列本身存在時,就是賦值。
frame['pop'] = np.arange(6.)
frame
    state   year    pop
0   Ohio    2000    0.0
1   Ohio    2001    1.0
2   Ohio    2002    2.0
3   Nevada  2001    3.0
4   Nevada  2002    4.0
5   Nevada  2003    5.0
#Series
val = pd.Series([1.2,4.3,5.7], index=[0,3,5])
frame['add'] = val
frame
    state   year    pop add
0   Ohio    2000    0.0 1.2
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7

使用del函數可以刪除某一列:

del frame['pop']
frame
    state   year
0   Ohio    2000
1   Ohio    2001
2   Ohio    2002
3   Nevada  2001
4   Nevada  2002
5   Nevada  2003

另一種常見的數據形式是嵌套字典:

data2 = {'Nevada':{2001:2.4, 2002:2.9},
        'Ohio':{2000:1.5, 2001:1.7, 2002:3.6}}
frame1 = pd.DataFrame(data2)
frame1
    Nevada  Ohio
2000    NaN 1.5
2001    2.4 1.7
2002    2.9 3.6

Tips:外層字典的鍵作為列,內層字典的鍵作為行索引。

對DataFrame進行轉值:

frame1.T
       2000 2001 2002
Nevada  NaN 2.4  2.9
Ohio    1.5 1.7  3.6

設置DataFrame的index和columns的name屬性:

frame1.index.name = 'year'
frame1.columns.name = 'state'
frame1
state   Nevada  Ohio
year        
2000    NaN 1.5
2001    2.4 1.7
2002    2.9 3.6

可以輸入給DataFrame構造器的數據類型:

Screen Shot 2019-06-13 at 16.22.31.png

pandas基本功能

本節(jié)介紹處理Series和DataFrame中的數據的基本手段,更詳細的pandas庫介紹可以看官網文檔User_Guide。

重新索引

pandas中的reindex是創(chuàng)建一個新的對象,使得數據符合新的索引。如果某個索引值當前不存在,則填入確實值。

obj4 = pd.Series([4.5,7.2,-5.3,3.6], index=['d','b','a','c'])
obj4
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64
obj5 = obj4.reindex(['a','b','c','d','e'])
obj5
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64
reindex函數的參數
參數 說明
index 用作索引的新序列
method 插值(填充)方式,ffill or pad 向前填充值;bfill or backfill 向后填充值
fill_value 引入缺失值時使用的替代值
limit 向前或向后填充時的最大填充量
tolerance 向前或向后填充時,填充不準確匹配項的最大間距(絕對距離)
level 在Multilndex的指定級別上匹配簡單索引,否則選取其子集
copy 默認為True,無論如何都復制;如果為False,則新舊相等就不復制

向前填充:

obj6 = pd.Series(['blue', 'yellow', 'orange'],index=[0,2,4])
obj6
0      blue
2    yellow
4    orange
dtype: object
obj6.reindex(range(6),method='ffill')
0      blue
1      blue
2    yellow
3    yellow
4    orange
5    orange
dtype: object

列可以用columns關鍵字重新索引:

frame2 = pd.DataFrame(np.arange(9).reshape((3,3),),
                     index=['a', 'c', 'd'],
                     columns=['Ohio', 'Texas', 'California'])
frame2
    Ohio    Texas   California
a   0       1       2
c   3       4       5
d   6       7       8
states = ['Ohio', 'Utah', 'California']
frame2.reindex(columns=states)
    Ohio    Utah    California
a   0       NaN     2
c   3       NaN     5
d   6       NaN     8

丟棄指定軸上的項drop函數

obj6.drop(2)
0      blue
4    orange
dtype: object
#axis=0 or axis='rows'傳遞為行(默認);axis=1 or axis='columns'傳遞為列
frame2.drop('Ohio', axis=1)
    Texas   California
a   1       2
c   4       5
d   7       8
#當drop函數中的參數設置為inplace=True時,就地修改對象,不會返回新的對象。必須要小心使用inplace,它會銷毀所有被刪除的數據

索引、選取和過濾

Series索引的工作方式類似于Numpy數組的索引,只不過Series的索引值不只是整數。

obj5
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64
#利用標簽切片運算與普通的Python的切片不同,其末端是包含的
obj5['a':'c']
a   -5.3
b    7.2
c    3.6
dtype: float64
#不用標簽索切片時,與Python的切片相同
obj5[:3]
a   -5.3
b    7.2
c    3.6
dtype: float64

用一個值或序列對DataFrame進行索引其實就是獲取一個或多個列:

frame
    state   year    pop add
0   Ohio    2000    0.0 1.2
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7
frame[['state', 'pop']]
    state   pop
0   Ohio    0.0
1   Ohio    1.0
2   Ohio    2.0
3   Nevada  3.0
4   Nevada  4.0
5   Nevada  5.0
frame[1:4]
    state   year    pop add
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
frame[frame['pop']>3]
    state   year    pop add
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7

用loc和iloc進行選

對于DataFrame的行的標簽索引,可以使用特殊的標簽運算符軸標簽loc和整數索引iloc。

frame.loc[3,['state', 'pop']]
state    Nevada
pop           3
Name: 3, dtype: object
#iloc可以這樣理解:不管有沒有設置新的行或列索引,默認的索引都是存在的,而iloc就是提取默認的索引值。
frame.iloc[3,[0,2]]
state    Nevada
pop           3
Name: 3, dtype: object

DataFrame數據選取與整合總結

類型 說明
df[val] 選取單列數據
df.loc[val] 通過標簽,選取DataFrame的單行數據
df.loc[:,val] 通過標簽,選取單列數據
df.loc[,val1, val2] 通過標簽,同時選取行和列對應的數據
df.iloc[where] 通過整數位置,選取單個行數據
df.oloc[:, where] 通過整數位置,選取單個列數據
df.iloc[where_i, where_j] 通過整數位置,同時選取行和列對應的數據
df.at[label_i, label_j] 通過行標簽和列標簽,選取對應的數據
df.iat[i,j] 通過行和列的位置(整數),選取對應的數據
reindex 通過標簽選取行或列
get_value,set_value 通過行和列標簽選取數據

算術運算和數據對齊

pandas最重要的一個功能是:對不同索引的對象進行算術運算,當數據相加時,如果存在不同索引,則結果的索引是所有數據索引的并集。

s1 = pd.Series([2,5,7,1], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([1,7,9,3,4], index=['a', 'c', 'e', 'f', 'g'])
s1
a    2
c    5
d    7
e    1
dtype: int64
s2
a    1
c    7
e    9
f    3
g    4
dtype: int64
#自動的數據對齊操作在不重疊的索引處引入了NA值,對于DataFrame會同時發(fā)生在行和列上
s1 + s2
a     3.0
c    12.0
d     NaN
e    10.0
f     NaN
g     NaN
dtype: float64

在算術方法中填充值

在對不同索引的對象進行算術運算時,我們可能希望當一個對象中某個軸標簽在另一個對象中找不到時填充一個特殊值(比如0)。此時可以使用算術方法在fill_value傳入參數0.

df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),
                  columns=list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),
                  columns=list('abcde'))
df1
    a   b   c   d
0   0.0 1.0 2.0 3.0
1   4.0 5.0 6.0 7.0
2   8.0 9.0 10.011.0
df2
    a   b   c   d   e
0   0.0 1.0 2.0 3.0 4.0
1   5.0 6.0 7.0 8.0 9.0
2   10.011.012.013.014.0
3   15.016.017.018.019.0
df1 + df2
    a   b   c   d   e
0   0.0 2.0 4.0 6.0 NaN
1   9.0 11.013.015.0NaN
2   18.020.022.024.0NaN
3   NaN NaN NaN NaN NaN
#填充值0
df1.add(df2,fill_value=0)
    a       b       c       d       e
0   0.0     2.0     4.0     6.0     4.0
1   9.0     11.0    13.0    15.0    9.0
2   18.0    20.0    22.0    24.0    14.0
3   15.0    16.0    17.0    18.0    19.0

Series和DataFrame算術方法

每個算術方法都有一個副本,以字母r開頭,它會翻轉參數。兩個語句等價。

方法 說明
add +加
sub, rsub -減
div, rdiv /除
floordiv, rfloordiv //底除
mul, rmul *乘
pow, rpow **指數

DataFrame和Series之間的運算

arr = np.arange(12).reshape((3,4))
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
arr[0]
array([0, 1, 2, 3])
#從arr減去arr[0],每一行都會執(zhí)行這個操作。這叫做廣播(broadcasting)
arr - arr[0]
array([[0, 0, 0, 0],
       [4, 4, 4, 4],
       [8, 8, 8, 8]])
#DataFrame和Series之間的運算差不多也是如此
frame3 = pd.DataFrame(np.arange(12).reshape((4,3)),
                     columns=list('abc'),
                     index=list('EMNF'))
frame3
    a   b   c
E   0   1   2
M   3   4   5
N   6   7   8
F   9   10  11
s3 = frame3.iloc[0]
s3
a    0
b    1
c    2
Name: E, dtype: int64
frame3 - s3
    a   b   c
E   0   0   0
M   3   3   3
N   6   6   6
F   9   9   9

如果希望在列上傳播,則必須使用算術運算方法。

s4 = frame3['a']
s4
E    0
M    3
N    6
F    9
Name: a, dtype: int64
frame3.sub(s4,axis='index')
    a   b   c
E   0   1   2
M   0   1   2
N   0   1   2
F   0   1   2

函數應用和映射

Numpy的函數也可以用于操作pandas對象:

np.add(frame3,2)
    a   b   c
E   2   3   4
M   5   6   7
N   8   9   10
F   11  12  13

另一個常見的操作是,將函數應用到各列或各行所形成的一維數組上。DataFrame的applay方法即可實現此功能。

frame3
    a   b   c
E   0   1   2
M   3   4   5
N   6   7   8
F   9   10  11
f = lambda x: x.max() - x.min()
frame3.apply(f)
a    9
b    9
c    9
dtype: int64

def f(x):
    return pd.Series([x.min(), x.max()], index=['min', 'max'])
frame3.apply(f, axis='columns')
    min max
E   0   2
M   3   5
N   6   8
F   9   11

frame4 = pd.DataFrame(np.random.randn(4,3),
                     columns=list('abc'),
                     index=list('DEFG'))
frame4
    a           b           c
D   0.279946    0.697885    -0.159838
E   -0.890032   0.480782    1.053987
F   -0.734350   -0.869877   0.439226
G   1.591106    0.822776    0.350413
#使用applymap函數得到frame4中各個浮點值的格式化字符串
f = lambda x: '%.2f' %x
frame4.applymap(f)
    a       b       c
D   0.28    0.70    -0.16
E   -0.89   0.48    1.05
F   -0.73   -0.87   0.44
G   1.59    0.82    0.35

結語:有關pandas的入門介紹就寫到此,上面的筆記都是自己看《利用Python進行數據分析》第五章節(jié)的記錄,絕大部分是書中的例題,也有一小部分是自己的添加的。

參考書籍:《利用Python進行數據分析》

2019-06-13

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容