1. 程式人生 > 實用技巧 >pandas資料處理基礎

pandas資料處理基礎

Pandas 資料處理基礎

1.Pandas介紹:

** Pandas 是非常著名的開源資料處理庫,我們可以通過它完成對資料集進行快速讀取、轉換、過濾、分析等一系列操作。除此之外,Pandas 擁有強大的缺失資料處理與資料透視功能,可謂是資料預處理中的必備利器。**

** Pandas 是非常著名的開源資料處理庫,其基於 NumPy 開發,該工具是 Scipy 生態中為了解決資料分析任務而設計。Pandas 納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的函式和方法。**

** 特有的資料結構是 Pandas 的優勢和核心。簡單來講,我們可以將任意格式的資料轉換為 Pandas 的資料型別,並使用 Pandas 提供的一系列方法進行轉換、操作,最終得到我們期望的結果。**

2.資料型別:

Pandas 的資料型別主要有以下幾種,它們分別是:Series(一維陣列),DataFrame(二維陣列),Panel(三維陣列),Panel4D(四維陣列),PanelND(更多維陣列)。其中 Series 和 DataFrame 應用的最為廣泛,幾乎佔據了使用頻率 90% 以上。

(1)Series:

Series 是 Pandas 中最基本的一維陣列形式。其可以儲存整數、浮點數、字串等型別的資料。** ​ 基本用法結構:

         
pandas.Series(data=None, index=None)

data 可以是字典,或者NumPy 裡的 ndarray 物件等。index 是資料索引,索引是 Pandas 資料結構中的一大特性,它主要的功能是幫助我們更快速地定位資料。**

具體實現:

%matplotlib inline
    import pandas as pd
    s = pd.Series({'a': 10, 'b': 20, 'c': 30})
    s   ==>  a    10
                  b    20
                  c    30
                 dtype: int64

通過 type 來確認 s 的型別:

type(s) ==>  pandas.core.series.Series

由於 Pandas 基於 NumPy 開發。那麼 NumPy 的資料型別 ndarray 多維陣列自然就可以轉換為 Pandas 中的資料。而 Series 則可以基於 NumPy 中的一維資料轉換。

import numpy as np
​
s = pd.Series(np.random.randn(5))
s ==>
0   -0.769720
1    0.047676
2    0.516502
3    1.570160
4   -0.200160
dtype: float64

如上所示,我們給出了 NumPy 生成的一維隨機陣列,最終得到的 Series 索引預設從 0 開始,而數值型別為 float64。

(2)DataFrame:

DataFrame 是 Pandas 中最為常見、最重要且使用頻率最高的資料結構。DataFrame 和平常的電子表格或 SQL 表結構相似。你可以把 DataFrame 看成是 Series 的擴充套件型別,它彷彿是由多個 Series 拼合而成。它和 Series 的直觀區別在於,資料不但具有行索引,且具有列索引。 ​ 基本用法結構:

pandas.DataFrame(data=None, index=None, columns=None)

區別於 Series,其增加了 columns 列索引

DataFrame 可以由以下多個型別的資料構建: 1) 一維陣列、列表、字典或者 Series 字典。 2) 二維或者結構化的 numpy.ndarray。 3) 一個 Series 或者另一個 DataFrame。

具體例子:

df = pd.DataFrame({'one': pd.Series([1, 2, 3]),
                  'two': pd.Series([4, 5, 6])})
df ==》
  onetwo
0   1 4
12 5
23 6

當不指定索引時,DataFrame 的索引同樣是從 0 開始。我們也可以直接通過一個列表構成的字典來生成 DataFrame。

df = pd.DataFrame({'one': [1, 2, 3],
                  'two': [4, 5, 6]})
df ==>
             one          two
0              1              4
1              2              5
2              3              6
#或者反過來,由帶字典的列表生成 DataFrame。
df = pd.DataFrame([{'one': 1, 'two': 4},
                  {'one': 2, 'two': 5},
                  {'one': 3, 'two': 6}])
df ==>
             one          two
0              1              4
1              2              5
2              3              6

NumPy 的多維陣列非常常用,同樣可以基於二維數值來構建一個 DataFrame。

pd.DataFrame(np.random.randint(5, size=(2, 4)))  
==>
              0               1              2             3
0              4               0              4             3
1              0               4              0             1

至此,你應該已經清楚了 Pandas 常用的 Series 和 DataFrame 資料型別。Series 實際上可以被初略看出是隻有 1 列資料的 DataFrame。當然,這個說法不嚴謹,二者的核心區別仍然是 Series 沒有列索引。你可以觀察如下所示由 NumPy 一維隨機陣列生成的 Series 和 DataFrame。

pd.Series(np.random.randint(5, size=(5,))) 
==> 
0    4
1    2
2    1
3    0
4    1
dtype: int64

pd.DataFrame(np.random.randint(5, size=(5,)))  
==> 	
               0
0              1
1              0
2              0
3              1
4              3

關於 Pandas 中的 Panel 等資料型別我們就不再介紹。首先是這些資料型別用的很少,其次就算你用到了,也可以通過從 DataFrame 等學到的技巧進行遷移應用,萬變不離其宗。

3.資料讀取

我們想要使用 Pandas 來分析資料,那麼首先需要讀取資料。大多數情況下,資料都來源於外部的資料檔案或者資料庫。Pandas 提供了一系列的方法來讀取外部資料,非常全面。

讀取資料 CSV 檔案的方法是 pandas.read_csv(),你可以直接傳入一個相對路徑,或者是網路 URL。

df = pd.read_csv("https://labfile.oss.aliyuncs.com/courses/906/los_census.csv")
df  ==> 
     Zip Code  Total Population  Median Age  Total Males  Total Females  
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households  Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

由於 CSV 儲存時是一個二維的表格,那麼 Pandas 會自動將其讀取為 DataFrame 型別。

現在你應該就明白了,DataFrame 是 Pandas 構成的核心。一切的資料,無論是外部讀取還是自行生成,我們都需要先將其轉換為 Pandas 的 DataFrame 或者 Series 資料型別。實際上,大多數情況下,這一切都是設計好的,無需執行額外的轉換工作。

pd.read_ 字首開始的方法還可以讀取各式各樣的資料檔案,且支援連線資料庫。這裡,我們不再依次贅述,你可以閱讀 官方文件相應章節 熟悉這些方法以及搞清楚這些方法包含的引數。

你可能又一個疑問:為什麼要將資料轉換為 Series 或者 DataFrame 結構? 實際上,我現在就可以先回答這個問題。因為 Pandas 針對資料操作的全部方法都是基於 Pandas 支援的資料結構設計的。也就是說,只有 Series 或者 DataFrame 才能使用 Pandas 提供的方法和函式進行處理。所以,學習真正資料處理方法之前,我們需要將資料轉換生成為 Series 或 DataFrame 型別。

4.基本操作

一個 DataFrame 結構大致由 3 部分組成,它們分別是列名稱、索引和資料。

上面,我們已經讀取了一個外部資料,這是洛杉磯的人口普查資料。有些時候,我們讀取的檔案很大。如果全部輸出預覽這些檔案,既不美觀,又很耗時。還好,Pandas 提供了 head() 和 tail() 方法,它可以幫助我們只預覽一小塊資料。

df.head()  # 預設顯示前 5 條 

輸出圖片:

df.tail(7)  # 指定顯示後 7 條
  ==> 
       Zip Code  Total Population  Median Age  Total Males  Total Females  \
312     93550             74929        27.5        36414          38515   
313     93551             50798        37.0        25056          25742   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households  Average Household Size  
312             20864                    3.58  
313             15963                    3.18  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67 

Pandas 還提供了統計和描述性方法,方便你從巨集觀的角度去了解資料集。describe() 相當於對資料集進行概覽,會輸出該資料集每一列資料的計數、最大值、最小值等。

df.describe()
==>
           Zip Code  Total Population  Median Age   Total Males  \
count    319.000000        319.000000  319.000000    319.000000   
mean   91000.673981      33241.341693   36.527586  16391.564263   
std      908.360203      21644.417455    8.692999  10747.495566   
min    90001.000000          0.000000    0.000000      0.000000   
25%    90243.500000      19318.500000   32.400000   9763.500000   
50%    90807.000000      31481.000000   37.100000  15283.000000   
75%    91417.000000      44978.000000   41.000000  22219.500000   
max    93591.000000     105549.000000   74.000000  52794.000000   

       Total Females  Total Households  Average Household Size  
count     319.000000        319.000000              319.000000  
mean    16849.777429      10964.570533                2.828119  
std     10934.986468       6270.646400                0.835658  
min         0.000000          0.000000                0.000000  
25%      9633.500000       6765.500000                2.435000  
50%     16202.000000      10968.000000                2.830000  
75%     22690.500000      14889.500000                3.320000  
max     53185.000000      31087.000000                4.670000  

Pandas 基於 NumPy 開發,所以任何時候你都可以通過 .values 將 DataFrame 轉換為 NumPy 陣列。

df.values  
==>
array([[9.1371e+04, 1.0000e+00, 7.3500e+01, ..., 1.0000e+00, 1.0000e+00,1.0000e+00],
       [9.0001e+04, 5.7110e+04, 2.6600e+01, ..., 2.8642e+04, 1.2971e+04,4.4000e+00],
       [9.0002e+04, 5.1223e+04, 2.5500e+01, ..., 2.6347e+04, 1.1731e+04,4.3600e+00],
         ...,
       [9.3560e+04, 1.8910e+04, 3.2400e+01, ..., 9.4190e+03, 6.4690e+03, 2.9200e+00],
       [9.3563e+04, 3.8800e+02, 4.4500e+01, ..., 1.2500e+02, 1.0300e+02,2.5300e+00],
       [9.3591e+04, 7.2850e+03, 3.0900e+01, ..., 3.6320e+03, 1.9820e+03,3.6700e+00]])

這也就說明了,你可以同時使用 Pandas 和 NumPy 提供的 API 對同一資料進行操作,並在二者之間進行隨意轉換。這就是一個非常靈活的工具生態圈。

除了 .values,DataFrame 支援的常見屬性可以通過 官方文件相應章節 檢視。其中常用的有:

df.index # 檢視索引RangeIndex(start=0, stop=319, step=1)
df.columns # 檢視列名 Index(['Zip Code', 'Total Population', 'Median Age', 'Total Males', 'Total Females', 'Total Households', 'Average Household Size'], dtype='object')
df.shape # 檢視形狀 (319, 7)

5.資料選擇

在資料預處理過程中,我們往往會對資料集進行切分,只將需要的某些行、列,或者資料塊保留下來,輸出到下一個流程中去。這也就是所謂的資料選擇,或者資料索引。

由於 Pandas 的資料結構中存在索引、標籤,所以我們可以通過多軸索引完成對資料的選擇。

(1)基於索引數字選擇

當我們新建一個 DataFrame 之後,如果未自己指定行索引或者列對應的標籤,那麼 Pandas 會預設從 0 開始以數字的形式作為行索引,並以資料集的第一行作為列對應的標籤。其實,這裡的「列」也有數字索引,預設也是從 0 開始,只是未顯示出來。

所以,我們首先可以基於數字索引對資料集進行選擇。這裡用到的 Pandas 中的 .iloc 方法。該方法可以接受的型別有:

1) 整數。例如:5 2) 整數構成的列表或陣列。例如:[1, 2, 3] 3) 布林陣列。 4) 可返回索引值的函式或引數。

首先,我們可以選擇前 3 行資料。

df.iloc[:3]  
==>  
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
1     90001             57110        26.6        28468          28642   
2     90002             51223        25.5        24876          26347   

   Total Households  Average Household Size  
0                 1                    1.00  
1             12971                    4.40  
2             11731                    4.36  
df.iloc[5]  
==> 
Zip Code                         90005.0
Total Population                 37681.0
Median Age                       33.9
Total Males                      19299.0
Total Females                    18382.0
Total Households                 15044.0
Average Household Size           2.5
Name: 5, dtype: float64

df.iloc[] 的 [[行],[列]] 裡面可以同時接受行和列的位置,如果你直接鍵入 df.iloc[1, 3, 5] 就會報錯。df.iloc[[]],選擇多行資料

df.iloc[[1, 3, 5]] 
==>
   Zip Code  Total Population  Median Age  Total Males  Total Females  \
1     90001             57110        26.6        28468          28642   
3     90003             66266        26.3        32631          33635   
5     90005             37681        33.9        19299          18382   

   Total Households  Average Household Size  
1             12971                    4.40  
3             15642                    4.22  
5             15044                    2.50  

選擇行學會以後,選擇列就應該能想到怎麼辦了。例如,我們要選擇第 2-4 列。

df.iloc[:, 1:4]  
==> 
         Total Population  Median Age  Total Males
0                   1        73.5            0
1               57110        26.6        28468
2               51223        25.5        24876
3               66266        26.3        32631
4               62180        34.8        31302
..                ...         ...          ...
314             38158        28.4        18711
315              2138        43.3         1121
316             18910        32.4         9491
317               388        44.5          263
318              7285        30.9         3653

[319 rows x 3 columns]

這裡選擇 2-4 列,輸入的卻是 1:4。這和 Python 或者 NumPy 裡面的切片操作非常相似。既然我們能定位行和列,那麼只需要組合起來,我們就可以選擇資料集中的任何資料了。

(2)基於標籤名稱選擇

除了根據數字索引選擇,還可以直接根據標籤對應的名稱選擇。這裡用到的方法和上面的 iloc 很相似,少了個 i 為 df.loc[]。

df.loc[] 可以接受的型別有: 1) 單個標籤。例如:2 或 'a',這裡的 2 指的是標籤而不是索引位置。 2) 列表或陣列包含的標籤。例如:['A', 'B', 'C']。 3) 切片物件。例如:'A':'E',注意這裡和上面切片的不同支援,首尾都包含在內。 4) 布林陣列。 5) 可返回標籤的函式或引數。

先選擇前 3 行:

df.loc[0:2]  
==>
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
1     90001             57110        26.6        28468          28642   
2     90002             51223        25.5        24876          26347   

   Total Households  Average Household Size  
0                 1                    1.00  
1             12971                    4.40  
2             11731                    4.36  

再選擇 1,3,5 行:

df.loc[[0, 2, 4]] 
==>
    Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
2     90002             51223        25.5        24876          26347   
4     90004             62180        34.8        31302          30878   

   Total Households  Average Household Size  
0                 1                    1.00  
2             11731                    4.36  
4             22547                    2.73 

然後,選擇 2-4 列:

df.loc[:, 'Total Population':'Total Males']  
==>
     Total Population  Median Age  Total Males
0                   1        73.5            0
1               57110        26.6        28468
2               51223        25.5        24876
3               66266        26.3        32631
4               62180        34.8        31302
..                ...         ...          ...
314             38158        28.4        18711
315              2138        43.3         1121
316             18910        32.4         9491
317               388        44.5          263
318              7285        30.9         3653

[319 rows x 3 columns]

最後,選擇 1,3 行和 Median Age 後面的列:

df.loc[[0, 2], 'Median Age':]  
==>
   Median Age  Total Males  Total Females  Total Households    Average Household Size
0        73.5            0              1                 1            1.00 
2        25.5        24876          26347             11731            4.3

6.資料刪減

雖然我們可以通過資料選擇方法從一個完整的資料集中拿到我們需要的資料,但有的時候直接刪除不需要的資料更加簡單直接。Pandas 中,以 .drop 開頭的方法都與資料刪減有關。

DataFrame.drop 可以直接去掉資料集中指定的列和行。一般在使用時,我們指定 labels 標籤引數,然後再通過 axis 指定按列或按行刪除即可。當然,你也可以通過索引引數刪除資料,具體檢視官方文件。

df.drop(labels=['Median Age', 'Total Males'], axis=1)
==> 
     Zip Code  Total Population  Total Females  Total Households  \
0       91371                 1              1                 1   
1       90001             57110          28642             12971   
2       90002             51223          26347             11731   
3       90003             66266          33635             15642   
4       90004             62180          30878             22547   
..        ...               ...            ...               ...   
314     93552             38158          19447              9690   
315     93553              2138           1017               816   
316     93560             18910           9419              6469   
317     93563               388            125               103   
318     93591              7285           3632              1982   

     Average Household Size  
0                      1.00  
1                      4.40  
2                      4.36  
3                      4.22  
4                      2.73  
..                      ...  
314                    3.93  
315                    2.62  
316                    2.92  
317                    2.53  
318                    3.67  

[319 rows x 5 columns]

DataFrame.drop_duplicates 則通常用於資料去重,即剔除資料集中的重複值。使用方法非常簡單,指定去除重複值規則,以及 axis 按列還是按行去除即可。

df.drop_duplicates()  
==> 
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households          Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

除此之外,另一個用於資料刪減的方法 DataFrame.dropna 也十分常用,其主要的用途是刪除缺少值,即資料集中空缺的資料列或行。

df.dropna() 
==>  
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households          Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

7.資料填充

Pandas 為了更方便地檢測缺失值,將不同型別資料的缺失均採用 NaN 標記。這裡的 NaN 代表 Not a Number,它僅僅是作為一個標記。例外是,在時間序列裡,時間戳的丟失採用 NaT 標記。

Pandas 中用於檢測缺失值主要用到兩個方法,分別是:isna() 和 notna(),故名思意就是「是缺失值」和「不是缺失值」。預設會返回布林值用於判斷。

接下來,我們人為生成一組包含缺失值的示例資料。

df = pd.DataFrame(np.random.rand(9, 5), columns=list('ABCDE'))

插入 T 列,並打上時間戳

df.insert(value=pd.Timestamp('2017-10-1'), loc=0, column='Time')

將 1, 3, 5 列的 1,3,5 行置為缺失值

df.iloc[[1, 3, 5, 7], [0, 2, 4]] = np.nan

將 2, 4, 6 列的 2,4,6 行置為缺失值

df.iloc[[2, 4, 6, 8], [1, 3, 5]] = np.nan
df  ==>  
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1        NaT  0.499374       NaN  0.834719       NaN  0.159916
2 2017-10-01       NaN  0.324404       NaN  0.457944       NaN
3        NaT  0.384484       NaN  0.582782       NaN  0.146258
4 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
5        NaT  0.530039       NaN  0.447082       NaN  0.738411
6 2017-10-01       NaN  0.000739       NaN  0.213739       NaN
7        NaT  0.799279       NaN  0.271489       NaN  0.407514
8 2017-10-01       NaN  0.246225       NaN  0.644346       NaN

然後,通過 isna() 或 notna() 中的一個即可確定資料集中的缺失值。

df.isna()  ==>     
Time      A      B      C      D      E
0  False  False  False  False  False  False
1   True  False   True  False   True  False
2  False   True  False   True  False   True
3   True  False   True  False   True  False
4  False   True  False   True  False   True
5   True  False   True  False   True  False
6  False   True  False   True  False   True
7   True  False   True  False   True  False
8  False   True  False   True  False   True

上面已經對預設值的產生、檢測進行了介紹。實際上,面對缺失值一般就是填充和剔除兩項操作。填充和清除都是兩個極端。如果你感覺有必要保留缺失值所在的列或行,那麼就需要對缺失值進行填充。如果沒有必要保留,就可以選擇清除缺失值。

其中,缺失值剔除的方法 dropna() 已經在上面介紹過了。下面來看一看填充缺失值 fillna() 方法。

首先,我們可以用相同的標量值替換 NaN,比如用 0。

print(df.fillna(0))  ==>
                  Time         A         B         C         D         E
0  2017-10-01 00:00:00  0.375561  0.509720  0.386046  0.942065  0.020290
1                    0  0.499374  0.000000  0.834719  0.000000  0.159916
2  2017-10-01 00:00:00  0.000000  0.324404  0.000000  0.457944  0.000000
3                    0  0.384484  0.000000  0.582782  0.000000  0.146258
4  2017-10-01 00:00:00  0.000000  0.924983  0.000000  0.620041  0.000000
5                    0  0.530039  0.000000  0.447082  0.000000  0.738411
6  2017-10-01 00:00:00  0.000000  0.000739  0.000000  0.213739  0.000000
7                    0  0.799279  0.000000  0.271489  0.000000  0.407514
8  2017-10-01 00:00:00  0.000000  0.246225  0.000000  0.644346  0.000000

除了直接填充值,我們還可以通過引數,將缺失值前面或者後面的值填充給相應的缺失值。例如使用缺失值前面的值進行填充:

df.fillna(method='pad')  ==> 
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01  0.384484  0.324404  0.582782  0.457944  0.146258
4 2017-10-01  0.384484  0.924983  0.582782  0.620041  0.146258
5 2017-10-01  0.530039  0.924983  0.447082  0.620041  0.738411
6 2017-10-01  0.530039  0.000739  0.447082  0.213739  0.738411
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

或者是後面的值:

df.fillna(method='bfill')  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
2 2017-10-01  0.384484  0.324404  0.582782  0.457944  0.146258
3 2017-10-01  0.384484  0.924983  0.582782  0.620041  0.146258
4 2017-10-01  0.530039  0.924983  0.447082  0.620041  0.738411
5 2017-10-01  0.530039  0.000739  0.447082  0.213739  0.738411
6 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
7 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514
8 2017-10-01       NaN  0.246225       NaN  0.644346       NaN

最後一行由於沒有對於的後序值,自然繼續存在缺失值。

上面的例子中,我們的缺失值是間隔存在的。那麼,如果存在連續的缺失值是怎樣的情況呢?試一試。首先,我們將資料集的第 2,4 ,6 列的第 3,5 行也置為缺失值。

df.iloc[[3, 5], [1, 3, 5]] = np.nan

然後來正向填充:

df.fillna(method='pad')  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
4 2017-10-01  0.499374  0.924983  0.834719  0.620041  0.159916
5 2017-10-01  0.499374  0.924983  0.834719  0.620041  0.159916
6 2017-10-01  0.499374  0.000739  0.834719  0.213739  0.159916
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

可以看到,連續缺失值也是按照前序數值進行填充的,並且完全填充。這裡,我們可以通過 limit= 引數設定連續填充的限制數量。

可以看到,連續缺失值也是按照前序數值進行填充的,並且完全填充。這裡,我們可以通過 limit= 引數設定連續填充的限制數量。

df.fillna(method='pad', limit=1)  # 最多填充一項  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01       NaN  0.324404       NaN  0.457944       NaN
4 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
5 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
6 2017-10-01       NaN  0.000739       NaN  0.213739       NaN
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

除了上面的填充方式,還可以通過 Pandas 自帶的求平均值方法等來填充特定列或行。舉個例子:

除了上面的填充方式,還可以通過 Pandas 自帶的求平均值方法等來填充特定列或行。舉個例子:

df.fillna(df.mean()['C':'E'])  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1        NaT  0.499374       NaN  0.834719  0.575627  0.159916
2 2017-10-01       NaN  0.324404  0.497418  0.457944  0.195907
3        NaT       NaN       NaN  0.497418  0.575627  0.195907
4 2017-10-01       NaN  0.924983  0.497418  0.620041  0.195907
5        NaT       NaN       NaN  0.497418  0.575627  0.195907
6 2017-10-01       NaN  0.000739  0.497418  0.213739  0.195907
7        NaT  0.799279       NaN  0.271489  0.575627  0.407514
8 2017-10-01       NaN  0.246225  0.497418  0.644346  0.195907

對 C 列到 E 列用平均值填充。

8.插值填充

插值是數值分析中一種方法。簡而言之,就是藉助於一個函式(線性或非線性),再根據已知資料去求解未知資料的值。插值在資料領域非常常見,它的好處在於,可以儘量去還原資料本身的樣子。

我們可以通過 interpolate() 方法完成線性插值。當然,其他一些插值演算法可以閱讀官方文件瞭解。

生成一個 DataFrame

df = pd.DataFrame({'A': [1.1, 2.2, np.nan, 4.5, 5.7, 6.9],
                   'B': [.21, np.nan, np.nan, 3.1, 11.7, 13.2]})
df ==>     
     A      B
0  1.1   0.21
1  2.2    NaN
2  NaN    NaN
3  4.5   3.10
4  5.7  11.70
5  6.9  13.20

對於上面存在的缺失值,如果通過前後值,或者平均值來填充是不太能反映出趨勢的。這時候,插值最好使。我們用預設的線性插值試一試。

df_interpolate = df.interpolate()
df_interpolate  ==>
      A          B
0  1.10   0.210000
1  2.20   1.173333
2  3.35   2.136667
3  4.50   3.100000
4  5.70  11.700000
5  6.90  13.200000

下圖展示了插值後的資料,明顯看出插值結果符合資料的變化趨勢。如果按照前後資料順序填充,則無法做到這一點。 對於 interpolate() 支援的插值演算法,也就是 method=。下面給出幾條選擇的建議: 1) 如果你的資料增長速率越來越快,可以選擇 method='quadratic'二次插值。 2) 如果資料集呈現出累計分佈的樣子,推薦選擇 method='pchip'。 3) 如果需要填補預設值,以平滑繪圖為目標,推薦選擇 method='akima'。

當然,最後提到的 method='akima',需要你的環境中安裝了 Scipy 庫。除此之外,method='barycentric' 和 method='pchip' 同樣也需要 Scipy 才能使用。

8.資料視覺化

NumPy,Pandas,Matplotlib 構成了一個完善的資料分析生態圈,所以 3 個工具的相容性也非常好,甚至共享了大量的介面。當我們的資料是以 DataFrame 格式呈現時,可以直接使用 Pandas 提供的 DataFrame.plot 方法呼叫 Matplotlib 介面繪製常見的圖形。

例如,我們使用上面插值後的資料 df_interpolate 繪製線形圖。

df_interpolate.plot()

輸出圖片:

其他樣式的圖形也很簡單,指定 kind= 引數即可。

df_interpolate.plot(kind='bar')  #柱狀圖

輸出圖片:

9.其他用法

由於 Pandas 包含的內容實在太多,除了閱讀完整的官方文件,很難做到通過一個實驗或者一個課程進行全面瞭解。當然,本課程的目的是帶大家熟悉 Pandas 的常用基礎方法,至少你大致清楚了 Pandas 是什麼,能幹什麼。

除了上面提到的一些方法和技巧,實際上 Pandas 常用的還有:

  • 資料計算,例如:DataFrame.add 等。

  • 資料聚合,例如:DataFrame.groupby 等。

  • 統計分析,例如:DataFrame.abs 等。

  • 時間序列,例如:DataFrame.shift 等。