Pandas 不擅長的結(jié)構(gòu)化數(shù)據(jù)運(yùn)算

Pandas 是 python 的一個(gè)數(shù)據(jù)分析包澄者,是基于 NumPy 的一種數(shù)據(jù)分析工具估脆,其中納入了大量庫和一些標(biāo)準(zhǔn)的數(shù)據(jù)模型,提供了快速便捷地處理數(shù)據(jù)的函數(shù)和方法虏等,是高效地操作結(jié)構(gòu)化數(shù)據(jù)集所需的工具民镜,也是使 Python 成為強(qiáng)大而高效的數(shù)據(jù)分析環(huán)境的重要因素之一啡专。

但是相信經(jīng)常使用 Pandas 的同學(xué)在處理結(jié)構(gòu)化數(shù)據(jù)運(yùn)算時(shí)也會(huì)遇到一些麻煩,這些問題要么使得問題解決很復(fù)雜(代碼難寫)制圈,要么使得運(yùn)行極其緩慢(效率低下)们童,下面總結(jié)整理了一些 Pandas 的困難問題進(jìn)行吐槽,如有謬誤歡迎指正鲸鹦,也歡迎大家參加到這次的“Pandas 吐槽大會(huì)”慧库。

切片賦值

切片賦值,指取數(shù)據(jù)中的某個(gè)值或某一塊值馋嗜,修改其中的值齐板,如把第 3 行第 5 列的 x 值修改為 y 值。

使用員工信息數(shù)據(jù)作為案例進(jìn)行介紹,數(shù)據(jù)片段如下:

問題一:將R&D 部門員工的工資改成 20000

Python 代碼

運(yùn)行結(jié)果:

SettingWithCopyWarning:

A value is trying to be set on a copy of a slice from a DataFrame.

Try using .loc[row_indexer,col_indexer] = value instead

可以看到甘磨,報(bào)了這個(gè) SettingWithCopyWarning橡羞,而且修改的值并沒有起作用。相信這個(gè)問題對(duì)于大多數(shù)的 Pandas 用戶并不陌生济舆,那么怎么修改呢卿泽?

就像 SettingWithCopyWarning 中提示的那樣,使用 df.loc[row_indexer,col_indexer] = value 進(jìn)行修改滋觉,這樣不僅可以得到正確的結(jié)果签夭,而且也可以解決報(bào)警的問題。

代碼修改如下:

//修改賦值

import pandas as ? pd

data = ? pd.read_csv('Employees.csv')

data.loc[data['DEPT']=='R&D','SALARY']=20000

print(data)

運(yùn)行結(jié)果:

這才是 Pandas 解決問題的方案椎侠。

討論:問題的實(shí)質(zhì)是我們想通過修改視圖修改源數(shù)據(jù)第租。而 data[data['DEPT']=='R&D']['SALARY']=2000 是將兩個(gè)索引操作鏈接在一起,即直接使用了兩次方括號(hào)的鏈?zhǔn)剿饕?/p>

1.???? data[data['DEPT']=='R&D']

2.???? ['SALARY']=20000

以上兩個(gè)鏈?zhǔn)讲僮饕粋€(gè)接一個(gè)地獨(dú)立執(zhí)行我纪。第一次鏈?zhǔn)讲僮魇菫榱?Get慎宾,返回一個(gè) DataFrame,其中包含所有 DEPT 等于 'R&D' 的行宣羊;第二次鏈?zhǔn)讲僮魇菫榱?Set璧诵,是在這個(gè)新返回的 DataFrame 上運(yùn)行的,并沒有修改原始的 DataFrame仇冯。而此時(shí)使用 loc 函數(shù)獲得原 DataFrame 的視圖,在視圖上賦值就可以修改原始 DataFrame 的值族操。


這種問題還是比較容易發(fā)現(xiàn)的苛坚,下面再來看一種情況:

問題二:修改 R&D 部門 5 號(hào)員工的工資為 19950

問題分析:在實(shí)際的工作中,經(jīng)常把視圖賦值給某個(gè)變量進(jìn)行后續(xù)的計(jì)算色难,直到某一步泼舱,又想修改其中的某行的值,此時(shí)再使用 loc 函數(shù)時(shí)也會(huì)出現(xiàn) SettingWithCopyWarning

Python 代碼:

運(yùn)行結(jié)果:

SettingWithCopyWarning:

A value is trying to be set on a copy of a slice from a DataFrame.

Try using .loc[row_indexer,col_indexer] = value instead

觀察發(fā)現(xiàn)枷莉,即使使用了 loc 函數(shù)娇昙,當(dāng)再次使用 loc 函數(shù)時(shí),還是會(huì)出現(xiàn) SettingWithCopyWarning 的報(bào)警笤妙,其中的原因還是將兩個(gè)索引操作鏈接在一起冒掌,第一次為 get,第二次為 set蹲盘。這次所不同的是賦值結(jié)果起作用了股毫,得到了我們期望的結(jié)果。但我們也不應(yīng)該忽略此 Warning召衔,而是應(yīng)該明確的告訴 Pandas 變量 r_d 是 data 中截取視圖的副本铃诬,然后再使用 loc 函數(shù)修改 5 號(hào)員工的工資。

代碼如下:

運(yùn)行結(jié)果:

討論:var=df.copy() 是明確的告知此 var 是 DataFrame 的副本,此時(shí)再使用 loc 函數(shù)賦值時(shí)趣席,就避免了兩次鏈?zhǔn)剿饕荆簿捅苊饬?SettingWithCopyWarning 的警告。

Pandas 針對(duì) df 的操作冷不防就會(huì)產(chǎn)生視圖宣肚,賦值時(shí)會(huì)錯(cuò)位毒姨,同時(shí)也會(huì)浪費(fèi)時(shí)間。

集合運(yùn)算

常見的集合運(yùn)算钉寝,包括交集弧呐,差集,并集嵌纲,異或集和和集運(yùn)算俘枫,下面來看下 Pandas 兩個(gè)集合間的運(yùn)算。

問題三:求銷售部門的員工與女員工的交集逮走,差集鸠蚪,并集,異或集和和集师溅。

Python 代碼:

討論:Pandas 集合運(yùn)算時(shí)茅信,只能對(duì)著索引進(jìn)行,然后再從原始數(shù)據(jù)中按索引截取得到結(jié)果墓臭。DataFrame 不可以直接進(jìn)行集合運(yùn)算蘸鲸。而且當(dāng)集合數(shù)多于兩個(gè)時(shí),需要通過循環(huán)兩兩計(jì)算得到結(jié)果窿锉,再從原始數(shù)據(jù)按索引截取酌摇。 當(dāng)希望按照某列進(jìn)行集合運(yùn)算時(shí),則還需要把該列轉(zhuǎn)成索引嗡载,計(jì)算完成后還要重置索引窑多,得到結(jié)果。對(duì)于簡單的集合運(yùn)算看起來就很麻煩洼滚,如果 Pandas 能支持集合 (set) 數(shù)據(jù)類型的集合運(yùn)算埂息,通過符號(hào) (&-|^) 進(jìn)行運(yùn)算就好了。

聚合運(yùn)算

Pandas 提供了很多聚合運(yùn)算函數(shù)遥巴,比如求和 sum()千康,平均 mean(),計(jì)數(shù) count()挪哄,方差 var()吧秕,標(biāo)準(zhǔn)差 std() 等等。但遇到稍微特殊一點(diǎn)聚合運(yùn)算時(shí)就有點(diǎn)麻煩迹炼,請(qǐng)看以下兩個(gè)問題砸彬。

問題四:查看所有工資最高的員工的信息

問題分析:首先找到最高工資颠毙,再篩選出等于最高工資的員工。

Python 代碼:

討論:這種方式需要遍歷兩邊數(shù)據(jù)砂碉,計(jì)算最大值時(shí)一遍蛀蜜,過濾時(shí)一遍,效率比較低增蹭。有一種方式可以只遍歷一遍滴某。即找最大值的同時(shí)記錄下最大值員工的索引,然后直接利用索引取數(shù)就可以了滋迈■荩可是 Pandas 的 idxmax() 函數(shù)只返回一個(gè)最大值的索引,不可以返回全部最大值的索引饼灿,因此就只能用上邊的笨方法來解決這個(gè)問題幕侠。


問題五:找到年齡最大的 5 位員工,即 TOPN 問題碍彭。

問題分析:最大值是相當(dāng)于 TOP1晤硕,因此 TOPN 問題也相當(dāng)于聚合運(yùn)算。

Python 代碼:

討論:TOPN 問題并不需要大排序庇忌,只需要維護(hù)一個(gè) N 長度的序列即可舞箍,保持序列中的 N 個(gè)數(shù)總是遍歷過的數(shù)據(jù)中的最大值或者最小值即可。大家都知道大排序的效率是很低的皆疹,而且當(dāng)數(shù)據(jù)量很大時(shí)疏橄,大排序復(fù)雜度和效率又會(huì)進(jìn)一步惡化。但 Pandas 并沒有提供高效的計(jì)算函數(shù)墙基。即使是 nlargest()和 nsmallest() 函數(shù)底層也是大排序后取前五软族。

定位計(jì)算

Pandas 提供了索引功能,用戶可以使用索引進(jìn)行切片等操作残制,但當(dāng)遇到需要計(jì)算指定索引(即位置)比前一行的行就比較麻煩剔氏,如下面這個(gè)問題:

問題六:計(jì)算股價(jià)超過 100 的交易日的當(dāng)日漲幅

問題分析:需要篩選出股價(jià)超過 100 的交易日的交易信息愧怜,將數(shù)據(jù)提前一天,使用相同的索引截取兩份數(shù)據(jù)所踊,計(jì)算兩者的漲幅浊闪。

Python 代碼:

討論:Python 并沒有提供利用位置進(jìn)行相關(guān)計(jì)算的函數(shù)恼布,所以計(jì)算這類問題就略顯麻煩。

分組運(yùn)算

Pandas 提供了豐富的分組運(yùn)算搁宾,既可以按照列名分組折汞,也可以按照指定的數(shù)組分組,既可以對(duì)單列使用多種方式聚合盖腿,也可以對(duì)多列聚合爽待,還可以循環(huán)各組损同,處理分組以后的集合。但有一些常見的分組運(yùn)算使用 Pandas 做起來要么比較繁瑣鸟款,要么效率低下膏燃。

比如按位置分組、值變化分組何什、條件變化分組都需要衍生出一個(gè)數(shù)組作為分組依據(jù)组哩,對(duì)位分組則需要使用 left join 的方式來繞,枚舉分組更是需要多次分組处渣,篩選需要的分組再合并伶贰,這里有一篇文章詳細(xì)介紹了 Pandas 分組運(yùn)算的一些例子

Python 分組處理

大家可以通過具體的例子體會(huì) Pandas 分組的不便之處。

并行運(yùn)算

Pandas 并不提供并行計(jì)算的方法罐栈,這也是 Pandas 被詬病最多的一方面黍衙,而 Python 所謂的多線程對(duì)于 CPU 而言還是單線程。


大數(shù)據(jù)計(jì)算

Pandas 雖然可以使用分段讀取的方式來獲取數(shù)據(jù)悠瞬,但想要實(shí)現(xiàn)一些復(fù)雜的運(yùn)算们豌,比如排序、分組浅妆、關(guān)聯(lián)等等都會(huì)非常非常麻煩望迎,而且對(duì)程序員的技術(shù)要求也會(huì)很高。詳細(xì)論述可以查看另一篇文檔凌外。

Python 如何處理大文件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辩尊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子康辑,更是在濱河造成了極大的恐慌摄欲,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疮薇,死亡現(xiàn)場(chǎng)離奇詭異胸墙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)按咒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門迟隅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人励七,你說我怎么就攤上這事智袭。” “怎么了掠抬?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵吼野,是天一觀的道長。 經(jīng)常有香客問我两波,道長瞳步,這世上最難降的妖魔是什么闷哆? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮谚攒,結(jié)果婚禮上阳准,老公的妹妹穿的比我還像新娘。我一直安慰自己馏臭,他們只是感情好野蝇,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著括儒,像睡著了一般绕沈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帮寻,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天乍狐,我揣著相機(jī)與錄音,去河邊找鬼固逗。 笑死浅蚪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烫罩。 我是一名探鬼主播惜傲,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼贝攒!你這毒婦竟也來了盗誊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤隘弊,失蹤者是張志新(化名)和其女友劉穎哈踱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梨熙,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡开镣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咽扇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哑子。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肌割,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帐要,我是刑警寧澤把敞,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站榨惠,受9級(jí)特大地震影響奋早,放射性物質(zhì)發(fā)生泄漏盛霎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一耽装、第九天 我趴在偏房一處隱蔽的房頂上張望愤炸。 院中可真熱鬧,春花似錦掉奄、人聲如沸规个。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诞仓。三九已至,卻和暖如春速兔,著一層夾襖步出監(jiān)牢的瞬間墅拭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工涣狗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谍婉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓镀钓,卻偏偏與公主長得像穗熬,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掸宛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容