數(shù)據(jù)類型
Pandas 的數(shù)據(jù)類型主要有以下幾種,它們分別是:Series(一維數(shù)組)逆屡,DataFrame(二維數(shù)組)前鹅,Panel(三維數(shù)組),Panel4D(四維數(shù)組)既棺,PanelND(更多維數(shù)組)讽挟。其中 Series 和 DataFrame 應(yīng)用的最為廣泛,幾乎占據(jù)了使用頻率 90% 以上丸冕。
Series
其可以儲(chǔ)存整數(shù)耽梅、浮點(diǎn)數(shù)、字符串等類型的數(shù)據(jù)胖烛。Series 基本結(jié)構(gòu)如下:
pandas.Series(data=None, index=None)
data 可以是字典眼姐,或者NumPy 里的 ndarray 對(duì)象等。index 是數(shù)據(jù)索引佩番,索引是 Pandas 數(shù)據(jù)結(jié)構(gòu)中的一大特性众旗,它主要的功能是幫助我們更快速地定位數(shù)據(jù)。
基于 Python 字典新建一個(gè)示例 Series趟畏。
%matplotlib inline
import pandas as pd
s = pd.Series({'a': 10, 'b': 20, 'c': 30})
s
該 Series 的數(shù)據(jù)值是 10, 20, 30贡歧,索引為 a, b, c,數(shù)據(jù)值的類型默認(rèn)識(shí)別為 int64±洌可以通過 type 來確認(rèn) s 的類型律想。
type(s)
Series 則可以基于 NumPy 中的一維數(shù)據(jù)轉(zhuǎn)換。
import numpy as np
s = pd.Series(np.random.randn(5))
s
最終得到的 Series 索引默認(rèn)從 0 開始绍弟,而數(shù)值類型為 float64技即。
DataFrame
DataFrame 是 Pandas 中最為常見、最重要且使用頻率最高的數(shù)據(jù)結(jié)構(gòu)樟遣。DataFrame 和平常的電子表格或 SQL 表結(jié)構(gòu)相似而叼。你可以把 DataFrame 看成是 Series 的擴(kuò)展類型,它仿佛是由多個(gè) Series 拼合而成豹悬。它和 Series 的直觀區(qū)別在于葵陵,數(shù)據(jù)不但具有行索引,且具有列索引瞻佛。
DataFrame 基本結(jié)構(gòu)如下:
pandas.DataFrame(data=None, index=None, columns=None)
DataFrame 可以由以下多個(gè)類型的數(shù)據(jù)構(gòu)建:
一維數(shù)組埃难、列表、字典或者 Series 字典涤久。
二維或者結(jié)構(gòu)化的 numpy.ndarray涡尘。
一個(gè) Series 或者另一個(gè) DataFrame。
使用一個(gè)由 Series 組成的字典來構(gòu)建 DataFrame响迂。
df = pd.DataFrame({'one': pd.Series([1, 2, 3]),
'two': pd.Series([4, 5, 6])})
df
當(dāng)不指定索引時(shí)考抄,DataFrame 的索引同樣是從 0 開始。我們也可以直接通過一個(gè)列表構(gòu)成的字典來生成 DataFrame蔗彤。
df = pd.DataFrame({'one': [1, 2, 3],
'two': [4, 5, 6]})
df
由帶字典的列表生成 DataFrame川梅。
df = pd.DataFrame([{'one': 1, 'two': 4},
{'one': 2, 'two': 5},
{'one': 3, 'two': 6}])
df
NumPy 的多維數(shù)組非常常用,同樣可以基于二維數(shù)值來構(gòu)建一個(gè) DataFrame然遏。
pd.DataFrame(np.random.randint(5, size=(2, 4)))
Series 實(shí)際上可以被初略看出是只有 1 列數(shù)據(jù)的 DataFrame贫途。當(dāng)然,這個(gè)說法不嚴(yán)謹(jǐn)待侵,二者的核心區(qū)別仍然是 Series 沒有列索引丢早。可以觀察如下所示由 NumPy 一維隨機(jī)數(shù)組生成的 Series 和 DataFrame秧倾。
pd.Series(np.random.randint(5, size=(5,)))
pd.DataFrame(np.random.randint(5, size=(5,)))
數(shù)據(jù)讀取
讀取數(shù)據(jù) CSV 文件的方法是 pandas.read_csv()怨酝,可以直接傳入一個(gè)相對(duì)路徑,或者是網(wǎng)絡(luò) URL那先。
df = pd.read_csv("https://labfile.oss.aliyuncs.com/courses/906/los_census.csv")
df
由于 CSV 存儲(chǔ)時(shí)是一個(gè)二維的表格农猬,那么 Pandas 會(huì)自動(dòng)將其讀取為 DataFrame 類型。
pd.read_ 前綴開始的方法還可以讀取各式各樣的數(shù)據(jù)文件售淡,且支持連接數(shù)據(jù)庫斤葱。
因?yàn)?Pandas 針對(duì)數(shù)據(jù)操作的全部方法都是基于 Pandas 支持的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)的慷垮。也就是說,只有 Series 或者 DataFrame 才能使用 Pandas 提供的方法和函數(shù)進(jìn)行處理揍堕。所以换帜,學(xué)習(xí)真正數(shù)據(jù)處理方法之前,我們需要將數(shù)據(jù)轉(zhuǎn)換生成為 Series 或 DataFrame 類型鹤啡。
基本操作
DataFrame 結(jié)構(gòu)大致由 3 部分組成,它們分別是列名稱蹲嚣、索引和數(shù)據(jù)递瑰。
有些時(shí)候,我們讀取的文件很大隙畜。如果全部輸出預(yù)覽這些文件抖部,既不美觀,又很耗時(shí)议惰。Pandas 提供了 head() 和 tail() 方法慎颗,它可以幫助我們只預(yù)覽一小塊數(shù)據(jù)。
df.head() # 默認(rèn)顯示前 5 條
df.tail(7) # 指定顯示后 7 條
Pandas 還提供了統(tǒng)計(jì)和描述性方法言询,方便你從宏觀的角度去了解數(shù)據(jù)集俯萎。describe() 相當(dāng)于對(duì)數(shù)據(jù)集進(jìn)行概覽,會(huì)輸出該數(shù)據(jù)集每一列數(shù)據(jù)的計(jì)數(shù)运杭、最大值夫啊、最小值等。
df.describe()
Pandas 基于 NumPy 開發(fā)辆憔,所以任何時(shí)候你都可以通過 .values 將 DataFrame 轉(zhuǎn)換為 NumPy 數(shù)組撇眯。
df.values
可以同時(shí)使用 Pandas 和 NumPy 提供的 API 對(duì)同一數(shù)據(jù)進(jìn)行操作,并在二者之間進(jìn)行隨意轉(zhuǎn)換虱咧。
df.index # 查看索引
df.columns # 查看列名
df.shape # 查看形狀
數(shù)據(jù)選擇
在數(shù)據(jù)預(yù)處理過程中熊榛,我們往往會(huì)對(duì)數(shù)據(jù)集進(jìn)行切分,只將需要的某些行腕巡、列玄坦,或者數(shù)據(jù)塊保留下來,輸出到下一個(gè)流程中去绘沉。這也就是所謂的數(shù)據(jù)選擇营搅,或者數(shù)據(jù)索引。
基于索引數(shù)字選擇
當(dāng)我們新建一個(gè) DataFrame 之后梆砸,如果未自己指定行索引或者列對(duì)應(yīng)的標(biāo)簽转质,那么 Pandas 會(huì)默認(rèn)從 0 開始以數(shù)字的形式作為行索引,并以數(shù)據(jù)集的第一行作為列對(duì)應(yīng)的標(biāo)簽帖世。其實(shí)休蟹,這里的「列」也有數(shù)字索引沸枯,默認(rèn)也是從 0 開始,只是未顯示出來赂弓。
我們首先可以基于數(shù)字索引對(duì)數(shù)據(jù)集進(jìn)行選擇绑榴。這里用到的 Pandas 中的 .iloc
方法。該方法可以接受的類型有:
整數(shù)盈魁。例如:5
整數(shù)構(gòu)成的列表或數(shù)組翔怎。例如:[1, 2, 3]
布爾數(shù)組。
可返回索引值的函數(shù)或參數(shù)杨耙。
首先赤套,我們可以選擇前 3 行數(shù)據(jù)。這和 Python 或者 NumPy 里面的切片很相似珊膜。
df.iloc[:3]
我們還可以選擇特定的一行容握。
df.iloc[5]
df.iloc[] 的 [[行],[列]] 里面可以同時(shí)接受行和列的位置车柠,如果你想要選擇 1剔氏,3,5 行竹祷,可以這樣做谈跛。
df.iloc[[1, 3, 5]]
我們要選擇第 2-4 列。
df.iloc[:, 1:4]
這里選擇 2-4 列塑陵,輸入的卻是 1:4币旧。這和 Python 或者 NumPy 里面的切片操作非常相似。既然我們能定位行和列猿妈,那么只需要組合起來吹菱,我們就可以選擇數(shù)據(jù)集中的任何數(shù)據(jù)了。
基于標(biāo)簽名稱選擇
除了根據(jù)數(shù)字索引選擇彭则,還可以直接根據(jù)標(biāo)簽對(duì)應(yīng)的名稱選擇鳍刷。為 df.loc[]
。
df.loc[] 可以接受的類型有:
單個(gè)標(biāo)簽俯抖。例如:2 或 'a'输瓜,這里的 2 指的是標(biāo)簽而不是索引位置。
列表或數(shù)組包含的標(biāo)簽芬萍。例如:['A', 'B', 'C']尤揣。
切片對(duì)象。例如:'A':'E'柬祠,注意這里和上面切片的不同之處北戏,首尾都包含在內(nèi)。
布爾數(shù)組漫蛔。
可返回標(biāo)簽的函數(shù)或參數(shù)嗜愈。
先選擇前 3 行:
df.loc[0:2]
再選擇 1旧蛾,3,5 行:
df.loc[[0, 2, 4]]
然后蠕嫁,選擇 2-4 列:
df.loc[:, 'Total Population':'Total Males']
最后锨天,選擇 1,3 行和 Median Age 后面的列:
df.loc[[0, 2], 'Median Age':]
數(shù)據(jù)刪減
以 .drop 開頭的方法都與數(shù)據(jù)刪減有關(guān)剃毒。
DataFrame.drop
可以直接去掉數(shù)據(jù)集中指定的列和行病袄。一般在使用時(shí),我們指定 labels
標(biāo)簽參數(shù)赘阀,然后再通過 axis
指定按列或按行刪除即可益缠。當(dāng)然,你也可以通過索引參數(shù)刪除數(shù)據(jù)纤壁,具體查看官方文檔。
df.drop(labels=['Median Age', 'Total Males'], axis=1)
DataFrame.drop_duplicates
則通常用于數(shù)據(jù)去重捺信,即剔除數(shù)據(jù)集中的重復(fù)值酌媒。使用方法非常簡單,指定去除重復(fù)值規(guī)則迄靠,以及 axis
按列還是按行去除即可秒咨。
df.drop_duplicates()
另一個(gè)用于數(shù)據(jù)刪減的方法 DataFrame.dropna
也十分常用,其主要的用途是刪除缺少值掌挚,即數(shù)據(jù)集中空缺的數(shù)據(jù)列或行雨席。
df.dropna()
數(shù)據(jù)填充
在真實(shí)的生產(chǎn)環(huán)境中,我們需要處理的數(shù)據(jù)文件往往沒有想象中的那么美好吠式。其中陡厘,很大幾率會(huì)遇到的情況就是缺失值。缺失值主要是指數(shù)據(jù)丟失的現(xiàn)象特占,也就是數(shù)據(jù)集中的某一塊數(shù)據(jù)不存在糙置。除此之外、存在但明顯不正確的數(shù)據(jù)也被歸為缺失值一類是目。例如谤饭,在一個(gè)時(shí)間序列數(shù)據(jù)集中,某一段數(shù)據(jù)突然發(fā)生了時(shí)間流錯(cuò)亂懊纳,那么這一小塊數(shù)據(jù)就是毫無意義的揉抵,可以被歸為缺失值。
檢測(cè)缺失值
Pandas 為了更方便地檢測(cè)缺失值嗤疯,將不同類型數(shù)據(jù)的缺失均采用 NaN 標(biāo)記冤今。這里的 NaN 代表 Not a Number,它僅僅是作為一個(gè)標(biāo)記茂缚。例外是辟汰,在時(shí)間序列里列敲,時(shí)間戳的丟失采用 NaT 標(biāo)記。
Pandas 中用于檢測(cè)缺失值主要用到兩個(gè)方法帖汞,分別是:isna()
和 notna()
戴而,故名思意就是「是缺失值」和「不是缺失值」。默認(rèn)會(huì)返回布爾值用于判斷翩蘸。
df = pd.DataFrame(np.random.rand(9, 5), columns=list('ABCDE'))
# 插入 T 列所意,并打上時(shí)間戳
df.insert(value=pd.Timestamp('2017-10-1'), loc=0, column='Time')
# 將 1, 3, 5 列的 1,3催首,5扶踊,7 行置為缺失值
df.iloc[[1, 3, 5, 7], [0, 2, 4]] = np.nan
# 將 2, 4, 6 列的 2,4郎任,6秧耗,8 行置為缺失值
df.iloc[[2, 4, 6, 8], [1, 3, 5]] = np.nan
df
然后,通過 isna()
或 notna()
中的一個(gè)即可確定數(shù)據(jù)集中的缺失值舶治。
df.isna()
面對(duì)缺失值一般就是填充和剔除兩項(xiàng)操作分井。填充和清除都是兩個(gè)極端。如果你感覺有必要保留缺失值所在的列或行霉猛,那么就需要對(duì)缺失值進(jìn)行填充尺锚。如果沒有必要保留,就可以選擇清除缺失值惜浅。
我們可以用相同的標(biāo)量值替換 NaN瘫辩,比如用 0。
df.fillna(0)
除了直接填充值坛悉,我們還可以通過參數(shù)伐厌,將缺失值前面或者后面的值填充給相應(yīng)的缺失值。例如使用缺失值前面的值進(jìn)行填充:
df.fillna(method='pad')
或者是后面的值:
df.fillna(method='bfill')
如果存在連續(xù)的缺失值是怎樣的情況呢裸影?試一試弧械。首先,我們將數(shù)據(jù)集的第 2空民,4 刃唐,6 列的第 3,5 行也置為缺失值界轩。
df.iloc[[3, 5], [1, 3, 5]] = np.nan
然后來正向填充:
df.fillna(method='pad')
可以看到画饥,連續(xù)缺失值也是按照前序數(shù)值進(jìn)行填充的,并且完全填充浊猾。這里抖甘,我們可以通過 limit= 參數(shù)設(shè)置連續(xù)填充的限制數(shù)量。
df.fillna(method='pad', limit=1) # 最多填充一項(xiàng)
除了上面的填充方式葫慎,還可以通過 Pandas 自帶的求平均值方法等來填充特定列或行衔彻。
df.fillna(df.mean()['C':'E'])
插值填充
插值是數(shù)值分析中一種方法薇宠。簡而言之,就是借助于一個(gè)函數(shù)(線性或非線性)艰额,再根據(jù)已知數(shù)據(jù)去求解未知數(shù)據(jù)的值澄港。插值在數(shù)據(jù)領(lǐng)域非常常見,它的好處在于柄沮,可以盡量去還原數(shù)據(jù)本身的樣子回梧。
我們可以通過 interpolate()
方法完成線性插值。當(dāng)然祖搓,其他一些插值算法可以閱讀官方文檔了解狱意。
# 生成一個(gè) 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
對(duì)于上面存在的缺失值,如果通過前后值拯欧,或者平均值來填充是不太能反映出趨勢(shì)的详囤。這時(shí)候,插值最好使镐作。我們用默認(rèn)的線性插值試一試藏姐。
df_interpolate = df.interpolate()
df_interpolate
下圖展示了插值后的數(shù)據(jù),明顯看出插值結(jié)果符合數(shù)據(jù)的變化趨勢(shì)滑肉。如果按照前后數(shù)據(jù)順序填充包各,則無法做到這一點(diǎn)摘仅。
對(duì)于
interpolate()
支持的插值算法靶庙,也就是 method=
。下面給出幾條選擇的建議:如果你的數(shù)據(jù)增長速率越來越快娃属,可以選擇 method='quadratic'二次插值六荒。
如果數(shù)據(jù)集呈現(xiàn)出累計(jì)分布的樣子,推薦選擇 method='pchip'矾端。
如果需要填補(bǔ)缺省值掏击,以平滑繪圖為目標(biāo),推薦選擇 method='akima'秩铆。
數(shù)據(jù)可視化
當(dāng)我們的數(shù)據(jù)是以 DataFrame 格式呈現(xiàn)時(shí)砚亭,可以直接使用 Pandas 提供的 DataFrame.plot
方法調(diào)用 Matplotlib 接口繪制常見的圖形。
例如殴玛,我們使用上面插值后的數(shù)據(jù) df_interpolate 繪制線形圖捅膘。
df_interpolate.plot()
其他樣式的圖形也很簡單,指定 kind= 參數(shù)即可滚粟。
df_interpolate.plot(kind='bar')
其他用法
* 數(shù)據(jù)計(jì)算*寻仗,例如:DataFrame.add
等。
* 數(shù)據(jù)聚合*凡壤,例如:DataFrame.groupby
等署尤。
* 統(tǒng)計(jì)分析*耙替,例如:DataFrame.abs
等。
* 時(shí)間序列*曹体,例如:DataFrame.shift
等俗扇。