入門Pandas不可不知的技巧
大家好,我是陽哥。
今天來跟大家分享 Pandas 的一些常用知識點,文章內(nèi)容由公眾號讀者 Peter 創(chuàng)作。
如果你用 Python 做數(shù)據(jù)分析,必然會繞不過 Pandas 的使用,實際上, Python 也是由于 numpy、pandas 等數(shù)據(jù)科學庫的出現(xiàn),才開始在數(shù)據(jù)科學領域?qū)崿F(xiàn)了快速的發(fā)展,因此,學好 Pandas 有很重要的現(xiàn)實意義。
本文總結自己經(jīng)常使用的pandas操作方法:
創(chuàng)建DataFrame數(shù)據(jù) 查看數(shù)據(jù)相關信息 查看頭尾文件 花樣取數(shù) 切片取數(shù) 常見函數(shù)使用
首先,導入包
import pandas as pd
import numpy as np
01 創(chuàng)建DataFrame數(shù)據(jù)
方式1:通過字典直接創(chuàng)建
df1 = pd.DataFrame({
"name":["小明","小紅","小孫","王小","關宇","劉蓓","張菲"],
"age":[20,18,27,20,28,18,25],
"sex":["男","女","男","男","男","女","女"],
"score":[669,570,642,590,601,619,701],
"address":["北京","深圳","廣州","武漢","深圳","廣州","長沙"]
})
df1
數(shù)據(jù)如下圖:

方式2:通過本地數(shù)據(jù)讀取
從本地文件中讀取進來?,F(xiàn)在本地有一個文件:學生信息.xlsx直接通過pd.read_excel()讀進來:
df2 = pd.read_excel("學生信息.xlsx")
df2

可以看到效果和上面是一樣的
02 數(shù)據(jù)探索
查看數(shù)據(jù)shape
shape表示數(shù)據(jù)是由多少行和列組成:
df1.shape # (7,5)
查看字段屬性名稱
df1.columns

查看屬性的數(shù)據(jù)類型
df1.dtypes

可以看到只有兩種數(shù)據(jù)類型:int64和object
查看數(shù)據(jù)是否缺失
df1.isnull() # 如果缺失顯示為True,否則顯示False

df1.isnull().sum() # 統(tǒng)計缺失值的個數(shù)。一個True計數(shù)一次

結果顯示:本次數(shù)據(jù)是沒有缺失值的
查看數(shù)據(jù)行索引
df1.index

查看數(shù)據(jù)描述信息
df1.describe

查看數(shù)據(jù)統(tǒng)計值
統(tǒng)計值信息只會顯示類型為數(shù)值型的數(shù)據(jù)統(tǒng)計值信息:
df1.describe()

統(tǒng)計值的結果包含:個數(shù)count、均值mean、方差std、最值min\max、四分位數(shù)25%、中位數(shù)50%、四分之三分位數(shù)75%。
03 查看頭尾文件
通過head和tail方法能夠快速查看數(shù)據(jù)的頭尾文件。
head
df1.head() # 默認是查看前5行數(shù)據(jù)
df1.head(3) # 指定顯示的行數(shù)
tail
df1.tail() # 默認尾部5行
df1.tail(3) # 指定尾部3行數(shù)據(jù)
04 花樣取數(shù)
從pandas的DataFrame數(shù)據(jù)框中取出我們想要的數(shù)據(jù),然后進行處理
取出某個字段的數(shù)據(jù)
我們?nèi)〕鰊ame這列的數(shù)據(jù):
name = df1["name"]
name
# 結果
0 小明
1 小紅
2 小孫
3 王小
4 關宇
5 劉蓓
6 張菲
Name: name, dtype: object
取出多個字段的數(shù)據(jù)
比如我們?nèi)〕鰊ame和age列的數(shù)據(jù):
name_age = df1[["name","age"]]
name_age
# 結果
name age
0 小明 20
1 小紅 18
2 小孫 27
3 王小 20
4 關宇 28
5 劉蓓 18
6 張菲 25
根據(jù)字段類型選擇數(shù)據(jù)
比如,我們想選擇字段類型為int64的數(shù)據(jù),通過查看的字段數(shù)據(jù)類型顯示:age和score都是int64類型
1、選擇單個數(shù)據(jù)類型
# 1、選擇單個數(shù)據(jù)類型
df1.select_dtypes(include='int64')
# 結果
age score
0 20 669
1 18 570
2 27 642
3 20 590
4 28 601
5 18 619
6 25 701
2、同時選擇多個類型
df1.select_dtypes(include=['int64','object'])
# 結果
name age sex score address
0 小明 20 男 669 北京
1 小紅 18 女 570 深圳
2 小孫 27 男 642 廣州
3 王小 20 男 590 武漢
4 關宇 28 男 601 深圳
5 劉蓓 18 女 619 廣州
6 張菲 25 女 701 長沙
因為數(shù)據(jù)中只有int64,object,所以我們?nèi)窟x出來了。
3、選擇排除某些數(shù)據(jù)類型之外的數(shù)據(jù):
# 選擇除了int64類型之外的數(shù)據(jù)
# 排除name和score字段之外的數(shù)據(jù)
df1.select_dtypes(exclude='int64')
# 結果
name sex address
0 小明 男 北京
1 小紅 女 深圳
2 小孫 男 廣州
3 王小 男 武漢
4 關宇 男 深圳
5 劉蓓 女 廣州
6 張菲 女 長沙
根據(jù)數(shù)值大小取數(shù)
1、直接通過判斷大小來取數(shù):
df1[df1["age"] == 20] # 年齡等于20
df1[df1["age"] != 20] # 年齡不等于20
df1[df1["age"] >= 20] # 年齡大于等于20
2、多個判斷條件連用

第一次使用上面的方法報錯:關鍵詞是ambiguous。判斷條件很讓pandas混淆,改成下面的寫法成功解決:
df1[(df1["age"] >= 20) & (df1["age"] < 27)]

根據(jù)字符串取數(shù)
1、通過單個條件取數(shù)
# 1、單條數(shù)據(jù)
df1[df1["name"] == "小明"]
# 結果
name age sex score address
0 小明 20 男 669 北京
2、通過多個條件取數(shù)
選擇姓名是小明,或者年齡大于25的數(shù)據(jù)
df1[(df1["name"] == "小明") | (df1["age"] > 25)]
# 結果
name age sex score address
0 小明 20 男 669 北京
2 小孫 27 男 642 廣州
4 關宇 28 男 601 深圳
3、字符串的開始、結尾、包含函數(shù)
str.startswith(string) str.endswith(string) str.contains(string)
# 1、取出以“小”開頭的姓名
df1[df1["name"].str.startswith("小")] # name以"小"開頭
# 結果
name age sex score address
0 小明 20 男 669 北京
1 小紅 18 女 570 深圳
2 小孫 27 男 642 廣州
# 以“關”開始
df1[df1["name"].str.startswith("關")]
# 結果
name age sex score address
4 關宇 28 男 601 深圳
# 3、以“菲”結尾
df1[df1["name"].str.endswith("菲")]
# 結果
name age sex score address
6 張菲 25 女 701 長沙
# 取出包含“小”的數(shù)據(jù):不管小是在開頭,還是結尾都會被選出來
df1[df1["name"].str.contains("小")]
# 結果
name age sex score address
0 小明 20 男 669 北京
1 小紅 18 女 570 深圳
2 小孫 27 男 642 廣州
3 王小 20 男 590 武漢
上面的王小不是小開頭,但是包含小,所以也被選出來。
4、字符串取反操作
取反符號是波浪線:~
下面的例子是:取出名字name中不包含小的數(shù)據(jù),只有3個人名字中沒有小字。
# 取出不包含小的數(shù)據(jù)
df1[~df1["name"].str.contains("小")]
# 結果
name age sex score address
4 關宇 28 男 601 深圳
5 劉蓓 18 女 619 廣州
6 張菲 25 女 701 長沙
05 切片取數(shù)
切片是Python中存在的概念,在pandas中同樣可以使用。切片中存在3個概念:start、stop、step
start:起始索引,包含 stop:結束索引,不包含 step:步長,可正可負;
寫法為:[start:stop:step]
步長為正數(shù)
1、通過下面的3個案例說明:起始索引默認從0開始,步長默認是1


2、指定起始索引,不指定結束索引,表示一直取到數(shù)據(jù)末尾
df1[4:] # 從索引4開始取到末尾
# 結果
name age sex score address
4 關宇 28 男 601 深圳
5 劉蓓 18 女 619 廣州
6 張菲 25 女 701 長沙
3、改變步長的值
df1[0:4:2] # 改變步長:每隔2個值取一行數(shù)據(jù)
# 結果
name age sex score address
0 小明 20 男 669 北京
2 小孫 27 男 642 廣州
上面的例子不指定起始索引:
df1[:4:2] # 默認從0開始
4、只指定步長
df1[::2] # 從頭到尾,步長為2
# 結果
name age sex score address
0 小明 20 男 669 北京
2 小孫 27 男 642 廣州
4 關宇 28 男 601 深圳
6 張菲 25 女 701 長沙
步長為負數(shù)
1、步長為-1,默認是倒序輸出結果
df1[::-1] # 倒序輸出
# 結果
name age sex score address
6 張菲 25 女 701 長沙
5 劉蓓 18 女 619 廣州
4 關宇 28 男 601 深圳
3 王小 20 男 590 武漢
2 小孫 27 男 642 廣州
1 小紅 18 女 570 深圳
0 小明 20 男 669 北京
2、步長為負,指定起始和終止索引,起始索引大于終止索引
df1[4:0:-1]
name age sex score address
4 關宇 28 男 601 深圳
3 王小 20 男 590 武漢
2 小孫 27 男 642 廣州
1 小紅 18 女 570 深圳
3、起始和終止索引為負數(shù)
df1[-1:-5:-1] # 最后一行記錄索引為-1,不包含索引為-5的數(shù)據(jù)
name age sex score address
6 張菲 25 女 701 長沙
5 劉蓓 18 女 619 廣州
4 關宇 28 男 601 深圳
3 王小 20 男 590 武漢
06 常用函數(shù)
統(tǒng)計元素個數(shù)
很多時候我們需要統(tǒng)計某個列中每個元素出現(xiàn)的個數(shù),相當于是做詞頻統(tǒng)計,使用:value_counts()方法,具體案例為:
??:新數(shù)據(jù)中df1增加了一列:班級class,后續(xù)有作用

比如我們想統(tǒng)計每個城市出現(xiàn)了多少次:
# 統(tǒng)計中每個城市各出現(xiàn)了多少次
address = df1["address"].value_counts()
address

結果自動是降序排列的Series類型數(shù)據(jù)
索引重置
索引重置使用reset_index():
address_new = address.reset_index()
address_new

還比如我們想從數(shù)據(jù)中單獨取出sex="男"的數(shù)據(jù):
fale = df1[df1["sex"] == "男"]
fale

我們觀察到數(shù)據(jù)前面的索引還是原來的,但是我們希望的是從0開始顯示,比較符合我們的習慣:
fale_1 = fale.reset_index()
fale_1

出現(xiàn)的結果中索引是我們想要的結果,但是出現(xiàn)了一列新的數(shù)據(jù),就是原來的索引構成的數(shù)據(jù),這不是我們想要的數(shù)據(jù),需要去除:
fale_1 = fale.reset_index(drop=True) # 加上參數(shù)即可解決
fale_1

屬性重命名
使用的是rename函數(shù),傳入columsn參數(shù):
address_new = address_new.rename(columns={"index":"address",
"address":"number"
})
address_new

groupby使用
groupby主要是實現(xiàn)分組統(tǒng)計的功能:
1、比如我們想統(tǒng)計男女各自的總分

# 統(tǒng)計男女的總成績:sum
sex_score = df1.groupby("sex")["score"].sum()
sex_score

2、求男女各自的平均分mean
# 統(tǒng)計男女的平均成績:mean
sex_score = df1.groupby("sex")["score"].mean()
sex_score

3、根據(jù)男女性別sex、班級class求總分
# 先根據(jù)性別、班級求總分
sex_class = df1.groupby(["sex","class"])["score"].sum()
sex_class

一行代碼實現(xiàn)上面的功能:
# 一行代碼實現(xiàn)
df1.groupby(["sex","class"])["score"].sum().reset_index()

apply函數(shù)
還是上面的df1數(shù)據(jù)集:

1、需求1:我們想將性別中的男變成1,女變成0
# 1、改變:男-1,女-0
df2 = df1.copy() # 生成一個副本
df2["sex"] = df2["sex"].apply(lambda x: 1 if x=="男" else 0) # 通過匿名函數(shù)解決
df2

我們還可以自定義一個函數(shù)來實現(xiàn):
# 自定義函數(shù)
def apply_sex(x):
return 1 if x == "男" else 0
df3 = df1.copy() # 生成一個副本df3
df3["sex"] = df3["sex"].apply(apply_sex) # 通過自定義函數(shù)解決
df3

2、還比如我們想給每個城市的后面加上一個“市”,變成北京市、深圳市等:
# 2、給每個城市加上一個字:市,變成北京市、深圳市等
df4 = df1.copy()
df4["address"] = df4["address"].apply(lambda x: x + "市")
df4

總結
本文中從pandas中DataFrame數(shù)據(jù)的創(chuàng)建,常見數(shù)據(jù)信息的探索,再到如何從數(shù)據(jù)框中獲取到我們指定的數(shù)據(jù),最后介紹了筆者常用的處理數(shù)據(jù)的方法,希望對入門或者對不熟悉pandas的朋友有所幫助。Pandas真的是十分強大,學好之后會大大節(jié)省我們處理數(shù)據(jù)的時間。
PS:公號內(nèi)回復「Python」即可進入Python 新手學習交流群,一起 100 天計劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點一下,如果感覺文章內(nèi)容不錯的話,記得分享朋友圈讓更多的人知道!


【代碼獲取方式】
