Python应用实战-Pandas 计算连续行为天数的几种思路
最近在處理數(shù)據(jù)的時候遇到一個需求,核心就是求取最大連續(xù)行為天數(shù)。
這里用北京空氣質(zhì)量數(shù)據(jù)作為案例進行演示,需求是找出北京空氣質(zhì)量連續(xù)污染最長持續(xù)多久并確定其周期。
圖1:案例數(shù)據(jù)
以上圖中數(shù)據(jù)來算,可以看到從1月21日-1月26日空氣質(zhì)量連續(xù)污染持續(xù)了6天。
不過,在實際的數(shù)據(jù)處理中,原始數(shù)據(jù)往往會較大,并不一定能直接看出來。接下來,介紹幾種解決方案供大家參考。
1. 獲取案例數(shù)據(jù)
大家可以通過以下方式獲取案例數(shù)據(jù)。
import?akshare?as?akair_quality_hist_df?=?ak.air_quality_hist(city="北京",?period="day",?start_date="2021-01-01",?end_date="2021-04-26") air_quality_hist_df.head()圖2:akshare數(shù)據(jù)預(yù)覽
由于只需要用到aqi,并按照國際標準進行優(yōu)良與污染定級,這里簡單做下數(shù)據(jù)處理如下:
import?pandas?as?pd#?重置索引 aqi?=?air_quality_hist_df['aqi'].reset_index() #?將aqi列改為int類型 aqi.aqi?=?aqi.aqi.astype('int') #?使用分箱進行空氣質(zhì)量定級 aqi['空氣質(zhì)量']?=?pd.cut(aqi.aqi,bins=[0,100,500],labels=['優(yōu)良','污染']) #?取10個樣本預(yù)覽 aqi.sample(10)圖3:處理后數(shù)據(jù)
2. 求連續(xù)污染持續(xù)天數(shù)
2.1. 思路1:按時間排序求差值再分組計數(shù)
才哥上次的解法就是這種思路,回看當初的代碼顯得比較稚嫩,今天我們看看小明哥的解法,非常精彩。
步驟1:篩選空氣質(zhì)量為污染的數(shù)據(jù)
t?=?aqi.query('空氣質(zhì)量=="污染"') t.sample(5)圖4:篩選空氣質(zhì)量污染的數(shù)據(jù)
步驟2:新增輔助列(輔助列可以不用加到原數(shù)據(jù)t上)
這里的邏輯大概如下:
-
輔助排名列(按照時間順序排序)為間隔天數(shù)
-
然后用時間字段(time)與間隔天數(shù)求差值得到一個日期
-
如果得到的這個日期相同,則這幾天是連續(xù)污染天
圖5:輔助列
步驟3:分組計數(shù)獲得連續(xù)天數(shù),分組求最小最大值獲得連續(xù) 污染起止日期
t.groupby(groupids).agg({'time':?lambda?x:f'{x.min()}~{x.max()}',?#?求起止日期'空氣質(zhì)量':"count",?#?求連續(xù)天數(shù) }).nlargest(5,'空氣質(zhì)量')?#?取?空氣質(zhì)量?字段最大的前5組數(shù)據(jù)圖6:解法1的結(jié)果
以上完整代碼如下:
t?=?aqi.query('空氣質(zhì)量=="污染"') t.groupby(pd.to_datetime(t.time)-pd.to_timedelta(t.time.rank(),unit='d')).agg({'time':?lambda?x:f'{x.min()}~{x.max()}','空氣質(zhì)量':"count",} ).nlargest(5,'空氣質(zhì)量')2.2. 思路2:比對相鄰兩天空氣質(zhì)量標記
思路2有兩種解法,其一是利用循環(huán)創(chuàng)建輔助列,其二是利用shift和cumsum創(chuàng)建輔助列,具體我們可以往下看。
解法1:利用循環(huán)創(chuàng)建輔助列
-
創(chuàng)建一個輔助列,輔助列的值按照以下思路創(chuàng)建函數(shù)獲取
-
如果空氣質(zhì)量為優(yōu)良,則輔助列值+1;若當前空氣質(zhì)量和上一日不同,則輔助列值也+1
-
以上均不滿足,則輔助列值不變
根據(jù)這個邏輯可以得到輔助列數(shù)據(jù)如下:
圖7:輔助列值預(yù)覽
可以發(fā)現(xiàn),按照輔助列分組進行計數(shù)即可獲得連續(xù)污染天數(shù),如上紅色標記區(qū)域。
aqi.groupby(groupids).agg({'time':?lambda?x:f'{x.min()}~{x.max()}','空氣質(zhì)量':"count",} ).nlargest(5,'空氣質(zhì)量')圖8:思路2的解法1結(jié)果
解法2:利用shift和cumsum創(chuàng)建輔助列
-
先創(chuàng)建空氣質(zhì)量的shift列,下移動一位
-
如果shift列和空氣質(zhì)量列相等,則判斷列為0,否則為1
-
輔助列為判斷列累加求和
圖9:輔助列創(chuàng)建思路預(yù)覽
我們也可以發(fā)現(xiàn),按照輔助列分組計數(shù)即可獲取空氣質(zhì)量連續(xù)天數(shù)(優(yōu)良和污染均可),如上紅色區(qū)域。
(aqi.query('空氣質(zhì)量=="污染"')?#?這里篩選?污染?天氣.groupby((aqi.空氣質(zhì)量.shift()?!=?aqi.空氣質(zhì)量).cumsum())?#?輔助列.time.agg(['count','min','max'])?#?計數(shù)及獲取日期區(qū)間.nlargest(5,'count') )圖9:思路2的解法2結(jié)果
按照小明哥的輸出結(jié)果,調(diào)整代碼如下:
( aqi.query("空氣質(zhì)量=='污染'") .groupby((aqi.空氣質(zhì)量 != aqi.空氣質(zhì)量.shift()).cumsum()) .agg( { 'time': lambda x: f"{x.min()}~{x.max()}", '空氣質(zhì)量': "count"} ).nlargest(5, '空氣質(zhì)量'))圖10:思路2的解法2小明哥結(jié)果
以上就是本次全部內(nèi)容,其實我們在日常工作生活中還可能遇到類似場景如:計算用戶連續(xù)登錄天數(shù)、計算用戶連續(xù)付費天數(shù)、計算南方梅雨季節(jié)連續(xù)下雨天數(shù)等等!
總結(jié)
以上是生活随笔為你收集整理的Python应用实战-Pandas 计算连续行为天数的几种思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python应用实战-用Python爬取
- 下一篇: Python应用实战-如何使用Plotl