本教程詳細闡述了如何利用pandas庫,在分組數(shù)據(jù)中高效地根據(jù)日期條件填充“截止日期”列。通過結(jié)合`groupby.ffill()`實現(xiàn)組內(nèi)向前填充缺失值,并利用`series.where()`進行條件篩選,確保只有當當前日期小于或等于填充的截止日期時,數(shù)據(jù)才會被更新,從而精確滿足復(fù)雜的數(shù)據(jù)填充需求。
在數(shù)據(jù)分析和處理中,尤其是在涉及時間序列或事件管理的數(shù)據(jù)集中,我們經(jīng)常需要對缺失值進行填充。然而,簡單的向前或向后填充往往不能滿足所有業(yè)務(wù)邏輯。一個常見的場景是,在一個按特定實體(例如“客戶-設(shè)備”)分組的數(shù)據(jù)集中,我們希望填充“截止日期”列的缺失值。但這種填充并非無條件的,它必須遵循一個重要的約束:只有當當前行的“日期”小于或等于被填充的“截止日期”時,該填充才有效。這意味著,一旦“日期”超出了有效的“截止日期”范圍,填充就應(yīng)該停止,或者該值應(yīng)該保持為NaN。
例如,考慮以下數(shù)據(jù)結(jié)構(gòu):
Customer-Equipment | Date | Closing Date |
---|---|---|
Customer1 - Eq A | 2023-01-01 | 2023-01-05 |
Customer1 - Eq A | 2023-01-02 | NaN |
Customer1 - Eq A | 2023-01-03 | NaN |
Customer1 - Eq A | 2023-01-04 | NaN |
Customer1 - Eq A | 2023-01-05 | NaN |
Customer1 - Eq A | 2023-01-06 | NaN |
Customer2 - Eq H | 2023-01-01 | 2023-01-02 |
Customer2 - Eq H | 2023-01-02 | NaN |
Customer2 - Eq H | 2023-01-03 | NaN |
我們的目標是將Customer1 - Equipment A的Closing Date從2023-01-02到2023-01-05填充為2023-01-05,因為這些Date值都小于或等于2023-01-05。但2023-01-06的Date超出了2023-01-05,所以該行的Closing Date應(yīng)保持為NaN。Customer2 - Equipment H也遵循相同的邏輯。
首先,我們創(chuàng)建一個示例DataFrame來模擬上述場景。確保日期列被正確解析為datetime類型,以便進行日期比較。
import pandas as pd import numpy as np # 創(chuàng)建示例數(shù)據(jù) data = { 'Customer-Equipment': [ 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer2 - Equipment H', 'Customer2 - Equipment H', 'Customer2 - Equipment H' ], 'Date': [ '2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05', '2023-01-06', '2023-01-01', '2023-01-02', '2023-01-03' ], 'Closing Date': [ '2023-01-05', np.nan, np.nan, np.nan, np.nan, np.nan, '2023-01-02', np.nan, np.nan ] } df = pd.DataFrame(data) # 將日期列轉(zhuǎn)換為datetime類型 df['Date'] = pd.to_datetime(df['Date']) df['Closing Date'] = pd.to_datetime(df['Closing Date']) print("原始DataFrame:") print(df)
原始DataFrame:
Customer-Equipment Date Closing Date 0 Customer1 - Equipment A 2023-01-01 2023-01-05 1 Customer1 - Equipment A 2023-01-02 NaT 2 Customer1 - Equipment A 2023-01-03 NaT 3 Customer1 - Equipment A 2023-01-04 NaT 4 Customer1 - Equipment A 2023-01-05 NaT 5 Customer1 - Equipment A 2023-01-06 NaT 6 Customer2 - Equipment H 2023-01-01 2023-01-02 7 Customer2 - Equipment H 2023-01-02 NaT 8 Customer2 - Equipment H 2023-01-03 NaT
解決此問題的關(guān)鍵在于兩個Pandas函數(shù)的巧妙結(jié)合:groupby.ffill()(組內(nèi)向前填充)和 Series.where()(條件篩選)。
首先,我們需要在每個Customer-Equipment組內(nèi),將Closing Date列的有效值向前傳播,以填充其后的NaN值。這可以通過groupby()結(jié)合ffill()方法實現(xiàn)。
# 對'Closing Date'列進行組內(nèi)向前填充 s_ffilled = df.groupby('Customer-Equipment')['Closing Date'].ffill() print("\n經(jīng)過ffill()填充后的Series:") print(s_ffilled)
經(jīng)過ffill()填充后的Series:
0 2023-01-05 1 2023-01-05 2 2023-01-05 3 2023-01-05 4 2023-01-05 5 2023-01-05 6 2023-01-02 7 2023-01-02 8 2023-01-02 Name: Closing Date, dtype: datetime64[ns]
此時,s_ffilled包含了所有潛在的填充值,但尚未考慮“日期”與“截止日期”的條件。例如,Customer1 - Equipment A的2023-01-06行也被填充為2023-01-05,這與我們的需求不符。
接下來,我們需要應(yīng)用條件:只有當Date列的值小于或等于填充后的Closing Date時,才保留填充值;否則,將其設(shè)置回NaN。Series.where()方法非常適合這種場景。它接受一個布爾條件,如果條件為True,則保留原值;如果條件為False,則替換為NaN(默認行為)或指定值。
在這里,我們的“原值”是s_ffilled,而“條件”是s_ffilled.ge(df['Date']),即判斷填充后的Closing Date是否大于或等于當前行的Date。
# 應(yīng)用條件篩選:只有當填充的截止日期 >= 當前日期時才保留 df['Closing Date'] = s_ffilled.where(s_ffilled.ge(df['Date']))
將上述兩個步驟整合到一起,形成完整的解決方案:
import pandas as pd import numpy as np # 1. 創(chuàng)建示例數(shù)據(jù) data = { 'Customer-Equipment': [ 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer1 - Equipment A', 'Customer2 - Equipment H', 'Customer2 - Equipment H', 'Customer2 - Equipment H' ], 'Date': [ '2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05', '2023-01-06', '2023-01-01', '2023-01-02', '2023-01-03' ], 'Closing Date': [ '2023-01-05', np.nan, np.nan, np.nan, np.nan, np.nan, '2023-01-02', np.nan, np.nan ] } df = pd.DataFrame(data) # 將日期列轉(zhuǎn)換為datetime類型 df['Date'] = pd.to_datetime(df['Date']) df['Closing Date'] = pd.to_datetime(df['Closing Date']) print("原始DataFrame:") print(df) # 2. 解決方案 # 步驟1: 對'Closing Date'列進行組內(nèi)向前填充 s_ffilled = df.groupby('Customer-Equipment')['Closing Date'].ffill() # 步驟2: 應(yīng)用條件篩選,只有當填充的截止日期 >= 當前日期時才保留 df['Closing Date'] = s_ffilled.where(s_ffilled.ge(df['Date'])) print("\n處理后的DataFrame:") print(df)
運行上述代碼后,我們將得到如下結(jié)果:
原始DataFrame: Customer-Equipment Date Closing Date 0 Customer1 - Equipment A 2023-01-01 2023-01-05 1 Customer1 - Equipment A 2023-01-02 NaT 2 Customer1 - Equipment A 2023-01-03 NaT 3 Customer1 - Equipment A 2023-01-04 NaT 4 Customer1 - Equipment A 2023-01-05 NaT 5 Customer1 - Equipment A 2023-01-06 NaT 6 Customer2 - Equipment H 2023-01-01 2023-01-02 7 Customer2 - Equipment H 2023-01-02 NaT 8 Customer2 - Equipment H 2023-01-03 NaT 處理后的DataFrame: Customer-Equipment Date Closing Date 0 Customer1 - Equipment A 2023-01-01 2023-01-05 1 Customer1 - Equipment A 2023-01-02 2023-01-05 2 Customer1 - Equipment A 2023-01-03 2023-01-05 3 Customer1 - Equipment A 2023-01-04 2023-01-05 4 Customer1 - Equipment A 2023-01-05 2023-01-05 5 Customer1 - Equipment A 2023-01-06 NaT 6 Customer2 - Equipment H 2023-01-01 2023-01-02 7 Customer2 - Equipment H 2023-01-02 2023-01-02 8 Customer2 - Equipment H 2023-01-03 NaT
可以看到,Customer1 - Equipment A組中,從2023-01-01到2023-01-05的Closing Date都被正確填充為2023-01-05,因為這些日期都小于或等于2023-01-05。而2023-01-06的Date超出了2023-01-05,因此其Closing Date保持為NaT(Pandas中的NaN日期類型)。Customer2 - Equipment H組也得到了同樣正確的處理。
本教程展示了一種高效且Pandas風格的方法,用于在分組數(shù)據(jù)中根據(jù)日期條件填充缺失值。通過結(jié)合groupby.ffill()進行組內(nèi)向前填充和Series.where()進行條件過濾,我們能夠精確地控制填充邏輯,滿足復(fù)雜的業(yè)務(wù)需求。這種方法不僅代碼簡潔,而且在處理大型數(shù)據(jù)集時通常具有良好的性能,是Pandas數(shù)據(jù)處理工具箱中的一個強大組合。
以上就是使用Pandas在分組數(shù)據(jù)中按條件填充“截止日期”的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號