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:
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 等。