
文章目錄
- 前文回顧
- DataFrame 核心分析方法
- 清洗資料
- 判斷行列中是否有空資料
- 清理行/列
- 去重
- 填充缺失值
- 消除資料中的空格
- 選擇資料
- pandas按列選擇資料
- filter方法選擇列
- pandas按行選擇資料
前文回顧
跟我一起學點 資料分析 – 第二天:上手pandas(2)
DataFrame 核心分析方法
清洗資料
python中用NaN(Not a Number)表示缺失資料
先搞一波資料來看看:
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
0 1 2
0 1.0 5.0 8.0
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
判斷行列中是否有空資料
axis=0,代表列,axis=1代表行
查看行:df.isnull().any(axis=1)
查看列:df.isnull().any(axis=0)
我弄了個按行判斷的你們看一下:
0 False
1 True
2 True
3 True
dtype: bool
再看一下這個:
查看行:df.notnull().all(axis=1)
查看列:df.notnull().all(axis=0)
這個的話,只要有非空資料,就會被判斷為True,
以上方法,都可以通過取反符號“~”來進行取反,
print(~df.isnull().any(axis = 1))
也可以通過loc()方法來進行取值,
比方說我要取出所有非空資料行,可以這樣來進行實作:
df = df.loc[~df.isnull().any(axis = 1)]
0 1 2
0 1.0 5.0 8.0
至于這個loc()方法,等會兒會說,
你也可以指定一列來進行空值的判斷:
print(df[1].isnull()) # 判斷一列的空值
print(df[1].isnull().value_counts()) # 對一列空值數量進行統計
清理行/列
相對來說有一個很直接的方法,直接將所有有空值的行、列進行清除:
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna()
print(df)
不附加任何的額外條件,只要你那一行里面存在空值,一行清理,
0 1 2
0 1.0 5.0 8.0
如果是要按列清理呢?那就加上:
df = pd.DataFrame([[1,5,8],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna(axis=1)
print(df)
啊,很遺憾的告訴你,全部被清理了,一點不剩,因為每一列都有空值啊,,,
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3]
好,那你現在跟我說,你覺得一行有那么一兩個壞值其實是可以忍受的,那我怎么辦?那我不還得給你辦嘛:
# 只要有n個值是好的,就留下:
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.dropna(thresh=1) # n
print(df)
0 1 2
0 1.0 5.0 8.0
2 2.0 3.0 NaN
對吧,那這要不是你想要的,那我也沒辦法了,
還有什么,洗掉指定列?洗掉指定行?那試試看嘛,摸索一下,
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.drop(labels=1)
print(df)
0 1 2
0 1.0 5.0 8.0
2 2.0 3.0 NaN
3 NaN NaN NaN
吶,我把那第一列刪了,
神乎其技!!!
df = pd.DataFrame([[1,5,8],[np.nan,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.drop(columns=2)
print(df)
不好意思,上面刪的是一行,這里才是刪一列,,,
0 1
0 1.0 5.0
1 NaN NaN
2 2.0 3.0
3 NaN NaN
哎,且看且珍惜吧,我不知道還能發多少了,
去重
如果你拿到一個資料集,非常大,你感覺里面有不少重復值,想要進行一波去重操作,怎么辦?
還有一個drop_duplicates還沒看,
換個資料集玩玩吧,一直用那個也累了,
df = pd.DataFrame({'Country':[1,1,2,12,34,23,45,34,23,12,2,3,4,1],
'Income':[1,1,2,10000, 10000, 5000, 5002, 40000, 50000, 8000, 5000,3000,15666,1],
'Age':[1,1,2,50, 43, 34, 40, 25, 25, 45, 32,12,32,1],
'group':[1,1,2,'a','b','s','d','f','g','h','a','d','a',1]})
Country Income Age group
0 1 1 1 1
1 1 1 1 1
2 2 2 2 2
3 12 10000 50 a
4 34 10000 43 b
5 23 5000 34 s
6 45 5002 40 d
7 34 40000 25 f
8 23 50000 25 g
9 12 8000 45 h
10 2 5000 32 a
11 3 3000 12 d
12 4 15666 32 a
13 1 1 1 1
直接上手去重:
df.drop_duplicates(inplace=True) #inplace=True 對原表進行修改
Country Income Age group
0 1 1 1 1
2 2 2 2 2
3 12 10000 50 a
4 34 10000 43 b
5 23 5000 34 s
6 45 5002 40 d
7 34 40000 25 f
8 23 50000 25 g
9 12 8000 45 h
10 2 5000 32 a
11 3 3000 12 d
12 4 15666 32 a
少了一列啊,
大家看資料表中的索引,在我們使用drop_duplicates洗掉重復行時,重復行相對應的索引值也是被默認洗掉掉的,也就是說,索引值已經發生了變化,
那我們該如何解決這個問題呢?
df.drop_duplicates(inplace=True)
df = df.reset_index(drop=True)
print(df)
Country Income Age group
0 1 1 1 1
1 2 2 2 2
2 12 10000 50 a
3 34 10000 43 b
4 23 5000 34 s
5 45 5002 40 d
6 34 40000 25 f
7 23 50000 25 g
8 12 8000 45 h
9 2 5000 32 a
10 3 3000 12 d
11 4 15666 32 a
如果要指定保留的重復行(默認是第一行),可以使用keep引數:一般沒什么給你選的,要么就first,要么就last,
對指定的資料列進行去重:
df.drop_duplicates(inplace=True,subset = ['Age'],keep='last')
df = df.reset_index(drop=True)
print(df)
0 2 2 2 2
1 12 10000 50 a
2 34 10000 43 b
3 23 5000 34 s
4 45 5002 40 d
5 23 50000 25 g
6 12 8000 45 h
7 3 3000 12 d
8 4 15666 32 a
9 1 1 1 1
如果要多幾行呢?
這操作叫什么?思考一下資料庫中的主鍵,
df.drop_duplicates(inplace=True,subset = ['Age','group'],keep='last')
df = df.reset_index(drop=True)
print(df)
Country Income Age group
0 2 2 2 2
1 12 10000 50 a
2 34 10000 43 b
3 23 5000 34 s
4 45 5002 40 d
5 34 40000 25 f
6 23 50000 25 g
7 12 8000 45 h
8 3 3000 12 d
9 4 15666 32 a
10 1 1 1 1
清理講到這里,接下來我們來填充缺失值,
填充缺失值
現在讓我們把資料集換回去,
然后填充一下缺失值:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
df = df.fillna(value=0) # 以指定值對缺失值進行填補
print(df)
0 1 2
0 1.0 5.0 0.0
1 2.0 0.0 0.0
2 2.0 3.0 0.0
3 0.0 0.0 0.0
用某一列的平均值對某一列進行填充:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
print(df)
df[1] = df.fillna(df[1].mean())
print(df)
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
0 1 2
0 1.0 5.0 1.0
1 2.0 NaN 2.0
2 2.0 3.0 2.0
3 NaN NaN NaN
要不你試試第二列?
吶,不指定列試試看:
df = pd.DataFrame([[1,5,np.nan],[2,np.nan,np.nan],[2,3,np.nan],[np.nan,np.nan,np.nan]])
print(df)
df = df.fillna(df.mean())
print(df)
自上而下填充:
df = df.fillna(method='ffill')
print(df)
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
0 1 2
0 1.0 5.0 NaN
1 2.0 5.0 NaN
2 2.0 3.0 NaN
3 2.0 3.0 NaN
有自上而下就有自下而上了:
df = df.fillna(method='bfill')
print(df)
0 1 2
0 1.0 5.0 NaN
1 2.0 NaN NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
0 1 2
0 1.0 5.0 NaN
1 2.0 3.0 NaN
2 2.0 3.0 NaN
3 NaN NaN NaN
再講個小技巧,但是也是很讓人煩惱的臟資料:空格
消除資料中的空格
# 創建含有空格的資料
dict1 = {"name": ["小紅", "小明", "小張"], "age": [16, 17, 18], "city": ["北京 ", "杭州", " 上海 "]}
df2 = pd.DataFrame(dict1, columns=["name", "age", "city"])
print(df2)
# 清除空格
df2["city"] = df2["city"].map(str.strip)
print(df2)
name age city
0 小紅 16 北京
1 小明 17 杭州
2 小張 18 上海
name age city
0 小紅 16 北京
1 小明 17 杭州
2 小張 18 上海
選擇資料
pandas按列選擇資料
就先來個最直觀的方式,直接中括號取值,
# 創建含有空格的資料
dict1 = {"name": ["小紅", "小明", "小張"], "age": [16, 17, 18], "city": ["北京 ", "杭州", " 上海 "]}
df2 = pd.DataFrame(dict1, columns=["name", "age", "city"])
# 清除空格
df2["city"] = df2["city"].map(str.strip)
print(df2['name'])
0 小紅
1 小明
2 小張
Name: name, dtype: object
當然,你要是不知道列名稱那怎么行?連列名都不知道還取個球,,,
print(df2.columns)
醬紫
Index(['name', 'age', 'city'], dtype='object')
一般都要選擇多列資料的,對吧,對吧!
行,我們來選取一下多列資料:
print(df2[['name','age']]) # 看清楚,傳進去的是一個串列,而不是兩個字串咯,
name age
0 小紅 16
1 小明 17
2 小張 18
按照資料型別選擇列
先來獲取一下當前DataFrame的資料列資料型別情況吧:
name object
age int64
city object
dtype: object
獲取一下object物件唄:
print(df2.select_dtypes(include='object'))
name city
0 小紅 北京
1 小明 杭州
2 小張 上海
那,如果說我要選擇‘object’物件以外的物件呢?
print(df2.select_dtypes(exclude='object'))
age
0 16
1 17
2 18
filter方法選擇列
它有三個常用引數,我們一個一個看,不過要注意:這三個引數并不能同時出現,
使用items選擇多個列:
df2 = df2.filter(items=['name','age'])
print(df2)
就跟上面那個直接取值的是一樣的,
name age
0 小紅 16
1 小明 17
2 小張 18
使用like選擇匹配的列:要求列名中含有,,,
df2 = df2.filter(like='a')
print(df2)
name age
0 小紅 16
1 小明 17
2 小張 18
使用正則運算式取列:
df2 = df2.filter(regex='[a-z]')
print(df2)
name age city
0 小紅 16 北京
1 小明 17 杭州
2 小張 18 上海
pandas按行選擇資料
先看個loc方法啊:
df2 = df2.loc[0:2]
print(df2)
name age city
0 小紅 16 北京
1 小明 17 杭州
2 小張 18 上海
你悟到了?
再來:
df2 = df2.loc[0:2,['name','age']]
name age
0 小紅 16
1 小明 17
2 小張 18
我就把結果放這兒,我就默默不說話,
df2 = df2.loc[(df2['age']>16) & (df2['age']<18)]
df2 = df2.loc[(df2['age']>16) | (df2['age']<18)]
這里我連結果都不想放了,發揮你們的想象力,
差不多了吧,我想想還有啥、、
lambda運算式,對、
df2 = df2.loc[lambda x:x.city == '北京']
吶,像這樣,
如果不出意外,這篇就到這里啦,see you!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/241852.html
標籤:python
下一篇:python爬蟲爬取圖片
