本篇針對Python語言的數據分析庫(pandas),分享了5個可以提升數據處理效率的解決方案,總結來說就是,不用不知道,一用真高效!符合真香定律···
針對不同情況下的nan值定位
涉及到數據的清洗,那么nan值必然是一個需要處理的問題,不論是直接舍棄還是填充值,總是需要先定位nan值在哪里,再根據數據特點去做相應的操作。這里我分享下我個人對定位nan值問題一些好的實踐
詳看以下代碼,主要包含三種情況的定位
import pandas as pd
import numpy as np
df = pd.DataFrame({"name": [i for i in list("abcde")], "age": [i for i in range(10, 15)], "female": ["f", np.nan, "m", np.nan, "m"]})
# 數據呈現是這個樣子
name age female
a 10 f
b 11 NaN
c 12 f
d 13 m
e 14 NaN
第一個方法:df.isnull().any()
通過結果可以看的出來,這個語句返回的是所有列是否含有nan值的布爾值
對于一個大數據文件來講,你想一瞬間知道哪些字段有nan值需要處理,那么這個命令就可以讓你瞬間看到結果,再針對結果做處理即可
# 結果展示 :顯示只有female列有nan值存在
name False
age False
female True
dtype: bool
第二個方法:df["female"].isnull()
結果如下,返回的是每個值是否為nan值的布爾值
第一個方法已經確定了哪些列有nan值,那么接下來你可能想知道的是這些字段中哪些值是nan值,那么這個方法就可以幫你定位
0 False
1 True
2 False
3 True
4 False
Name: female, dtype: bool
第三個方法:df[df.isnull().values==True]
結果如下:返回的是數據表中含有nan值的所有行
還有個寫法很推薦, df[df.列名.isnull().values==True],因為有些列的nan值沒有什么實際作用,也不用處理,那么有些列則必須不能有nan值,那么就可以通過這個命令專門針對某一列進行nan值的定位
這個命令是我用的最多的,因為在大數據文件中,如果nan值非常少,那么這種方法的定位非常有有效率且直接
# 結果展示 :返回所有存在nan值
name age female
1 b 11 NaN
3 d 13 NaN
把每個人的愛好匯總
有的時候你會面臨一種情況:你需要把某一列的值根據一定的分組要求分類聚合到一起,然后統一進行一系列的運算,需求如下所示
# 構建案例數據
import pandas as pd
df = pd.DataFrame({"name": ["小明", "小明", "小明", "小明", "小明", "小明", "小紅", "小紅", "小紅", "小紅", "小紅"],
"愛好": ["籃球", "足球", "乒乓球", "唱歌", "跳舞", "跳繩", "喝酒", "抽煙", "燙頭", "蹦迪", "瑜伽"]})
# 數據呈現如下
name 愛好
0 小明 籃球
1 小明 足球
2 小明 乒乓球
3 小明 唱歌
4 小明 跳舞
5 小明 跳繩
6 小紅 喝酒
7 小紅 抽煙
8 小紅 燙頭
9 小紅 蹦迪
10 小紅 瑜伽
需求結果要如下所示
# 我們發現需求簡單來說 就是將小明和小紅的愛好匯總到一起
name 愛好
0 小明 籃球,足球,乒乓球,唱歌,跳舞,跳繩
1 小紅 喝酒,抽煙,燙頭,蹦迪,瑜伽
想要實現這個效果,代碼如下
# 先分組,然后將分組內容聚合(這里是以“,”連接)
new_df = df.groupby(["name"])["愛好"].Apply(lambda x: x.str.cat(sep=",")).reset_index()
一波反向操作
有時候在篩選數據集的時候條件很復雜,但是這些復雜的對立條件卻只有一個,這種情況下就可以通過對立條件篩選反集,篩選所需要的數據,一般來講,涉及到"isin"的時候有可能用的到
import numpy as np
import pandas as pd
df = pd.DataFrame({"省": ["遼寧", "遼寧", "遼寧", "四川", "四川", "四川", "四川", "山東", "山東"], "市": ["沈陽", "大連", "盤錦", "成都", "資陽", "綿陽","樂山", "青島", "菏澤"]})
# 數據呈現如下
省 市
0 遼寧 沈陽
1 遼寧 大連
2 遼寧 盤錦
3 四川 成都
4 四川 資陽
5 四川 綿陽
6 四川 樂山
7 山東 青島
8 山東 菏澤
需求描述為:要呈現除了沈陽之外的數據
#實現代碼如下, 這種就可以直接取反集,直接將沈陽的排除
df = df[~(df.市 == "沈陽")]
# 結果呈現如下
省 市
1 遼寧 大連
2 遼寧 盤錦
3 四川 成都
4 四川 資陽
5 四川 綿陽
6 四川 樂山
7 山東 青島
8 山東 菏澤
將每個人的技能拆分成序列展示
有時候我們會面對這種需求:一個字段中保存的是帶有固定分隔符的字符串(比如", "),需要將這一行的這個字段拆分,拆分為一個數據集,這個數據集每一行都顯示這個原有字段的一個值
這么說有點繞口,看圖
# 基礎數據
import pandas as pd
df = pd.DataFrame({"name": ["小明", "小紅", "小陳", "小白", "小王"], "技能": ["籃球,排球,羽毛球", "乒乓球,籃球,排球", "網球,唱歌,跳舞", "b-box,籃球,足球", "網球,乒乓球,羽毛球"]})
# 構造數據如下所示
name 技能
0 小明 籃球,排球,羽毛球
1 小紅 乒乓球,籃球,排球
2 小陳 網球,唱歌,跳舞
3 小白 b-box,籃球,足球
4 小王 網球,乒乓球,羽毛球
需求為:需要把技能相同的人匯總一起,那么首先第一步肯定是要將每個人技能拆開,再去做聚合操作,那么拆開的結果應該是如下圖所示的
# 將小明的技能分開展示,小紅,小陳也是如此
name 技能-分開
0 小明 籃球
0 小明 排球
0 小明 羽毛球
1 小紅 乒乓球
1 小紅 籃球
1 小紅 排球
2 小陳 網球
2 小陳 唱歌
2 小陳 跳舞
3 小白 b-box
3 小白 籃球
3 小白 足球
4 小王 網球
4 小王 乒乓球
4 小王 羽毛球
實現代碼
# 用到了拼接和轉置的操作
df=df.drop('技能', axis=1).join(df['技能'].str.split(',', expand=True).stack().reset_index(level=1, drop=True).rename('技能-分開'))
只關注各省份TOP2的記錄
需求描述:我想將數據根據一定的要求分類并排序,然后取每個分組后排序的前兩條記錄
舉例來說就是,如下
import numpy as np
import pandas as pd
df = pd.DataFrame({"省": ["遼寧", "遼寧", "遼寧", "四川", "四川", "四川", "四川", "山東", "山東"], "市": ["沈陽", "大連", "盤錦", "成都", "資陽", "綿陽","樂山", "青島", "菏澤"]})
# 根據數據集大小將某列生成隨機模擬數
df["籃球場個數"] = np.random.randint(1000000, 5000000, size=len(df))
# 數據如下所示
省 市 籃球場個數
0 遼寧 沈陽 4697737
1 遼寧 大連 3550960
2 遼寧 盤錦 3154660
3 四川 成都 1174838
4 四川 資陽 4409197
5 四川 綿陽 2188212
6 四川 樂山 1609722
7 山東 青島 3724735
8 山東 菏澤 2102416
需求為:展示每個省籃球場個數最多的前兩個市,展示如下
# 每個省市只展示前兩名的數據集
省 市 籃球場個數
0 遼寧 沈陽 4697737
1 遼寧 大連 3550960
3 四川 成都 1174838
4 四川 資陽 4409197
7 山東 青島 3724735
8 山東 菏澤 2102416
之前我計算這個,要用for循環迭代去取值,后面了解到了這個方法,效率提升了幾倍,怎么寫,如下所示
# 先排名,根據省市和籃球場個數,要加上inplace=True, 不然沒有更改原表的順序
df.sort_values(by=["省", "籃球場個數"], ascending=False, inplace=True)
print(df)
# 根據省份分組,并取每個組的前兩條記錄,則為排名前兩名的記錄,一定要用變量接受結果
tmp_df = df.groupby(by=["省"]).head(2)