Pandas之:Pandas簡潔教程

flydean發表於2021-06-05

Pandas之:Pandas簡潔教程

簡介

pandas是建立在Python程式語言之上的一種快速,強大,靈活且易於使用的開源資料分析和處理工具,它含有使資料清洗和分析⼯

作變得更快更簡單的資料結構和操作⼯具。pandas經常和其它⼯具⼀同使⽤,如數值計算⼯具NumPy和SciPy,分析庫statsmodels和scikit-learn,和資料視覺化庫matplotlib等。

pandas是基於NumPy陣列構建的,雖然pandas採⽤了⼤量的NumPy編碼⻛格,但⼆者最⼤的不同是pandas是專⻔為處理表格和混雜資料設計的。⽽NumPy更適合處理統⼀的數值陣列資料。

本文是關於Pandas的簡潔教程。

物件建立

因為Pandas是基於NumPy陣列來構建的,所以我們在引用的時候需要同時引用Pandas和NumPy:

In [1]: import numpy as np

In [2]: import pandas as pd

Pandas中最主要的兩個資料結構是Series和DataFrame。

Series和一維陣列很相似,它是由NumPy的各種資料型別來組成的,同時還包含了和這組資料相關的index。

我們來看一個Series的例子:

In [3]: pd.Series([1, 3, 5, 6, 8])
Out[3]:
0    1
1    3
2    5
3    6
4    8
dtype: int64

左邊的是索引,右邊的是值。因為我們在建立Series的時候並沒有指定index,所以index是從0開始到n-1結束。

Series在建立的時候還可以傳入np.nan表示空值:

In [4]: pd.Series([1, 3, 5, np.nan, 6, 8])
Out[4]:
0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64

DataFrame是⼀個表格型的資料結構,它含有⼀組有序的列,每列可以是不同的值型別(數值、字串、布林值等)。

DataFrame既有⾏索引也有列索引,它可以被看做由Series組成的字典(共⽤同⼀個索引)。

看一個建立DataFrame的例子:

In [5]: dates = pd.date_range('20201201', periods=6)

In [6]: dates
Out[6]:
DatetimeIndex(['2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04',
               '2020-12-05', '2020-12-06'],
              dtype='datetime64[ns]', freq='D')

上面我們建立了一個index的list。

然後使用這個index來建立一個DataFrame:

In [7]:  pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
Out[7]:
                   A         B         C         D
2020-12-01  1.536312 -0.318095 -0.737956  0.143352
2020-12-02  1.325221  0.065641 -2.763370 -0.130511
2020-12-03 -1.143560 -0.805807  0.174722  0.427027
2020-12-04 -0.724206  0.050155 -0.648675 -0.645166
2020-12-05  0.182411  0.956385  0.349465 -0.484040
2020-12-06  1.857108  1.245928 -0.767316 -1.890586

上面的DataFrame接收三個引數,第一個引數是DataFrame的表格資料,第二個引數是index的值,也可以看做是行名,第三個引數是列名。

還可以直接傳入一個字典來建立一個DataFrame:

In [9]: pd.DataFrame({'A': 1.,
   ...:                         'B': pd.Timestamp('20201202'),
   ...:                         'C': pd.Series(1, index=list(range(4)), dtype='float32'),
   ...:                         'D': np.array([3] * 4, dtype='int32'),
   ...:                         'E': pd.Categorical(["test", "train", "test", "train"]),
   ...:                         'F': 'foo'})
   ...:
Out[9]:
     A          B    C  D      E    F
0  1.0 2020-12-02  1.0  3   test  foo
1  1.0 2020-12-02  1.0  3  train  foo
2  1.0 2020-12-02  1.0  3   test  foo
3  1.0 2020-12-02  1.0  3  train  foo

上面的DataFrame中,每個列都有不同的資料型別。

我們用個圖片來更好的理解DataFrame和Series:

它就像是Excel中的表格,帶有行頭和列頭。

DataFrame中的每一列都可以看做是一個Series:

檢視資料

建立好Series和DataFrame之後,我們就可以檢視他們的資料了。

Series可以通過index和values來獲取其索引和值資訊:

In [10]: data1 = pd.Series([1, 3, 5, np.nan, 6, 8])

In [12]: data1.index
Out[12]: RangeIndex(start=0, stop=6, step=1)

In [14]: data1.values
Out[14]: array([ 1.,  3.,  5., nan,  6.,  8.])

DataFrame可以看做是Series的集合,所以DataFrame帶有更多的屬性:

In [16]: df.head()
Out[16]:
                   A         B         C         D
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599
2020-12-03  0.610846  0.216937  0.821258  0.805818
2020-12-04  0.490105  0.732421  0.547129 -0.443274
2020-12-05 -0.475531 -0.853141  0.160017  0.986973

In [17]: df.tail(3)
Out[17]:
                   A         B         C         D
2020-12-04  0.490105  0.732421  0.547129 -0.443274
2020-12-05 -0.475531 -0.853141  0.160017  0.986973
2020-12-06  0.288091 -2.164323  0.193989 -0.197923

head跟tail分別取得DataFrame的頭幾行和尾部幾行。

同樣的DataFrame也有index和columns:

In [19]: df.index
Out[19]:
DatetimeIndex(['2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04',
               '2020-12-05', '2020-12-06'],
              dtype='datetime64[ns]', freq='D')

In [20]: df.values
Out[20]:
array([[ 0.44624818, -0.0605494 , -0.44566462, -1.39250227],
       [-1.11974917, -1.65977552, -0.61865617,  1.97159943],
       [ 0.61084596,  0.2169369 ,  0.82125808,  0.80581847],
       [ 0.49010504,  0.73242082,  0.54712889, -0.44327351],
       [-0.47553134, -0.85314134,  0.16001748,  0.98697257],
       [ 0.28809148, -2.16432292,  0.19398863, -0.19792266]])

describe方法可以對資料進行統計:

In [26]: df.describe()
Out[26]:
              A         B         C         D
count  6.000000  6.000000  6.000000  6.000000
mean   0.040002 -0.631405  0.109679  0.288449
std    0.687872  1.128019  0.556099  1.198847
min   -1.119749 -2.164323 -0.618656 -1.392502
25%   -0.284626 -1.458117 -0.294244 -0.381936
50%    0.367170 -0.456845  0.177003  0.303948
75%    0.479141  0.147565  0.458844  0.941684
max    0.610846  0.732421  0.821258  1.971599

還可以對DataFrame進行轉置:

In [27]: df.T
Out[27]:
   2020-12-01  2020-12-02  2020-12-03  2020-12-04  2020-12-05  2020-12-06
A    0.446248   -1.119749    0.610846    0.490105   -0.475531    0.288091
B   -0.060549   -1.659776    0.216937    0.732421   -0.853141   -2.164323
C   -0.445665   -0.618656    0.821258    0.547129    0.160017    0.193989
D   -1.392502    1.971599    0.805818   -0.443274    0.986973   -0.197923

可以按行和按列進行排序:

In [28]: df.sort_index(axis=1, ascending=False)
Out[28]:
                   D         C         B         A
2020-12-01 -1.392502 -0.445665 -0.060549  0.446248
2020-12-02  1.971599 -0.618656 -1.659776 -1.119749
2020-12-03  0.805818  0.821258  0.216937  0.610846
2020-12-04 -0.443274  0.547129  0.732421  0.490105
2020-12-05  0.986973  0.160017 -0.853141 -0.475531
2020-12-06 -0.197923  0.193989 -2.164323  0.288091

In [29]: df.sort_values(by='B')
Out[29]:
                   A         B         C         D
2020-12-06  0.288091 -2.164323  0.193989 -0.197923
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599
2020-12-05 -0.475531 -0.853141  0.160017  0.986973
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502
2020-12-03  0.610846  0.216937  0.821258  0.805818
2020-12-04  0.490105  0.732421  0.547129 -0.443274

選擇資料

通過DataFrame的列名,可以選擇代表列的Series:

In [30]: df['A']
Out[30]:
2020-12-01    0.446248
2020-12-02   -1.119749
2020-12-03    0.610846
2020-12-04    0.490105
2020-12-05   -0.475531
2020-12-06    0.288091
Freq: D, Name: A, dtype: float64

通過切片可以選擇行:

In [31]: df[0:3]
Out[31]:
                   A         B         C         D
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599
2020-12-03  0.610846  0.216937  0.821258  0.805818

或者這樣:

In [32]: df['20201202':'20201204']
Out[32]:
                   A         B         C         D
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599
2020-12-03  0.610846  0.216937  0.821258  0.805818
2020-12-04  0.490105  0.732421  0.547129 -0.443274

loc和iloc

使用loc可以使用軸標籤來選取資料。

In [33]: df.loc[:, ['A', 'B']]
Out[33]:
                   A         B
2020-12-01  0.446248 -0.060549
2020-12-02 -1.119749 -1.659776
2020-12-03  0.610846  0.216937
2020-12-04  0.490105  0.732421
2020-12-05 -0.475531 -0.853141
2020-12-06  0.288091 -2.164323

前面是行的選擇,後面是列的選擇。

還可以指定index的名字:

In [34]: df.loc['20201202':'20201204', ['A', 'B']]
Out[34]:
                   A         B
2020-12-02 -1.119749 -1.659776
2020-12-03  0.610846  0.216937
2020-12-04  0.490105  0.732421

如果index的名字不是切片的話,將會給資料降維:

In [35]: df.loc['20201202', ['A', 'B']]
Out[35]:
A   -1.119749
B   -1.659776
Name: 2020-12-02 00:00:00, dtype: float64

如果後面列是一個常量的話,直接返回對應的值:

In [37]: df.loc['20201202', 'A']
Out[37]: -1.1197491665145112

iloc是根據值來選取資料,比如我們選擇第三行:

In [42]: df.iloc[3]
Out[42]:
A    0.490105
B    0.732421
C    0.547129
D   -0.443274
Name: 2020-12-04 00:00:00, dtype: float64

它其實和df.loc['2020-12-04']是等價的:

In [41]: df.loc['2020-12-04']
Out[41]:
A    0.490105
B    0.732421
C    0.547129
D   -0.443274
Name: 2020-12-04 00:00:00, dtype: float64

同樣可以傳入切片:

In [43]: df.iloc[3:5, 0:2]
Out[43]:
                   A         B
2020-12-04  0.490105  0.732421
2020-12-05 -0.475531 -0.853141

可以傳入list:

In [44]: df.iloc[[1, 2, 4], [0, 2]]
Out[44]:
                   A         C
2020-12-02 -1.119749 -0.618656
2020-12-03  0.610846  0.821258
2020-12-05 -0.475531  0.160017

取具體某個格子的值:

In [45]: df.iloc[1, 1]
Out[45]: -1.6597755161871708

布林索引

DataFrame還可以通過布林值來進行索引,下面是找出列A中所有元素大於0的:

In [46]: df[df['A'] > 0]
Out[46]:
                   A         B         C         D
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502
2020-12-03  0.610846  0.216937  0.821258  0.805818
2020-12-04  0.490105  0.732421  0.547129 -0.443274
2020-12-06  0.288091 -2.164323  0.193989 -0.197923

或者找出整個DF中,值大於0的:

In [47]: df[df > 0]
Out[47]:
                   A         B         C         D
2020-12-01  0.446248       NaN       NaN       NaN
2020-12-02       NaN       NaN       NaN  1.971599
2020-12-03  0.610846  0.216937  0.821258  0.805818
2020-12-04  0.490105  0.732421  0.547129       NaN
2020-12-05       NaN       NaN  0.160017  0.986973
2020-12-06  0.288091       NaN  0.193989       NaN

可以給DF新增一列:

In [48]: df['E'] = ['one', 'one', 'two', 'three', 'four', 'three']

In [49]: df
Out[49]:
                   A         B         C         D      E
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one
2020-12-03  0.610846  0.216937  0.821258  0.805818    two
2020-12-04  0.490105  0.732421  0.547129 -0.443274  three
2020-12-05 -0.475531 -0.853141  0.160017  0.986973   four
2020-12-06  0.288091 -2.164323  0.193989 -0.197923  three

使用isin()來進行範圍值的判斷判斷:

In [50]: df[df['E'].isin(['two', 'four'])]
Out[50]:
                   A         B         C         D     E
2020-12-03  0.610846  0.216937  0.821258  0.805818   two
2020-12-05 -0.475531 -0.853141  0.160017  0.986973  four

處理缺失資料

現在我們的df有a,b,c,d,e這5列,如果我們再給他加一列f,那麼f的初始值將會是NaN:

In [55]: df.reindex(columns=list(df.columns) + ['F'])
Out[55]:
                   A         B         C         D      E   F
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one NaN
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one NaN
2020-12-03  0.610846  0.216937  0.821258  0.805818    two NaN
2020-12-04  0.490105  0.732421  0.547129 -0.443274  three NaN
2020-12-05 -0.475531 -0.853141  0.160017  0.986973   four NaN
2020-12-06  0.288091 -2.164323  0.193989 -0.197923  three NaN

我們給前面的兩個F賦值:

In [74]: df1.iloc[0:2,5]=1

In [75]: df1
Out[75]:
                   A         B         C         D      E    F
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one  1.0
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one  1.0
2020-12-03  0.610846  0.216937  0.821258  0.805818    two  NaN
2020-12-04  0.490105  0.732421  0.547129 -0.443274  three  NaN
2020-12-05 -0.475531 -0.853141  0.160017  0.986973   four  NaN
2020-12-06  0.288091 -2.164323  0.193989 -0.197923  three  NaN

可以drop所有為NaN的行:

In [76]: df1.dropna(how='any')
Out[76]:
                   A         B         C         D    E    F
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502  one  1.0
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599  one  1.0

可以填充NaN的值:

In [77]: df1.fillna(value=5)
Out[77]:
                   A         B         C         D      E    F
2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one  1.0
2020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one  1.0
2020-12-03  0.610846  0.216937  0.821258  0.805818    two  5.0
2020-12-04  0.490105  0.732421  0.547129 -0.443274  three  5.0
2020-12-05 -0.475531 -0.853141  0.160017  0.986973   four  5.0
2020-12-06  0.288091 -2.164323  0.193989 -0.197923  three  5.0

可以對值進行判斷:

In [78]:  pd.isna(df1)
Out[78]:
                A      B      C      D      E      F
2020-12-01  False  False  False  False  False  False
2020-12-02  False  False  False  False  False  False
2020-12-03  False  False  False  False  False   True
2020-12-04  False  False  False  False  False   True
2020-12-05  False  False  False  False  False   True
2020-12-06  False  False  False  False  False   True

合併

DF可以使用Concat來合併多個df,我們先建立一個df:

In [79]: df = pd.DataFrame(np.random.randn(10, 4))

In [80]: df
Out[80]:
          0         1         2         3
0  1.089041  2.010142 -0.532527  0.991669
1  1.303678 -0.614206 -1.358952  0.006290
2 -2.663938  0.600209 -0.008845 -0.036900
3  0.863718 -0.450501  1.325427  0.417345
4  0.789239 -0.492630  0.873732  0.375941
5  0.327177  0.010719 -0.085967 -0.591267
6 -0.014350  1.372144 -0.688845  0.422701
7 -3.355685  0.044306 -0.979253 -2.184240
8 -0.051961  0.649734  1.156918 -0.233725
9 -0.692530  0.057805 -0.030565  0.209416

然後把DF拆成三部分:

In [81]: pieces = [df[:3], df[3:7], df[7:]]

最後把使用concat把他們合起來:

In [82]: pd.concat(pieces)
Out[82]:
          0         1         2         3
0  1.089041  2.010142 -0.532527  0.991669
1  1.303678 -0.614206 -1.358952  0.006290
2 -2.663938  0.600209 -0.008845 -0.036900
3  0.863718 -0.450501  1.325427  0.417345
4  0.789239 -0.492630  0.873732  0.375941
5  0.327177  0.010719 -0.085967 -0.591267
6 -0.014350  1.372144 -0.688845  0.422701
7 -3.355685  0.044306 -0.979253 -2.184240
8 -0.051961  0.649734  1.156918 -0.233725
9 -0.692530  0.057805 -0.030565  0.209416

還可以使用join來進行類似SQL的合併:

In [83]: left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})

In [84]: right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})

In [85]: left
Out[85]:
   key  lval
0  foo     1
1  foo     2

In [86]: right
Out[86]:
   key  rval
0  foo     4
1  foo     5

In [87]: pd.merge(left, right, on='key')
Out[87]:
   key  lval  rval
0  foo     1     4
1  foo     1     5
2  foo     2     4
3  foo     2     5

分組

先看上面的DF:

In [99]: df2
Out[99]:
   key  lval  rval
0  foo     1     4
1  foo     1     5
2  foo     2     4
3  foo     2     5

我們可以根據key來進行group,從而進行sum:

In [98]: df2.groupby('key').sum()
Out[98]:
     lval  rval
key
foo     6    18

group還可以按多個列進行:

In [100]: df2.groupby(['key','lval']).sum()
Out[100]:
          rval
key lval
foo 1        9
    2        9

本文已收錄於 http://www.flydean.com/01-python-pandas-overview/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章