[英]Python pandas dataframe: Find last occurrence of value less-than-or-equal-to current row
[英]Python Pandas - Minutes since last occurrence in 2 million row dataframe
舉個例子,我有以下數據幀:
Date indicator_1 indicator_2
2013-04-01 03:50:00 x w
2013-04-01 04:00:00 y u
2013-04-01 04:15:00 z v
2013-04-01 04:25:00 x w
2013-04-01 04:25:00 z u
2013-04-01 04:30:00 y u
2013-04-01 04:35:00 y w
2013-04-01 04:40:00 z w
2013-04-01 04:40:00 x u
2013-04-01 04:40:00 y v
2013-04-01 04:50:00 x w
我的目標是使用以下規則創建兩列:
第一列應該給出自indicator_1列上最后一次出現'x'以來的分鍾數。
第二列應該給出自指標_1上的“y”和“指標_2”列上的“u”最后一次出現以來的分鍾數。
對於具有相同精確小時且其中一個時間對應於'x'(在第一種情況下)或對'y','u'(在第二種情況下)中的行,計算分鍾數應該針對先前出現的變量做出。 因此,所需的輸出應該是這樣的:
Date desired_column_1 desired_column_2 indicator_1 indicator_2
2013-04-01 03:50:00 NaN NaN x w
2013-04-01 04:00:00 10.0 NaN y u
2013-04-01 04:15:00 25.0 15.0 z v
2013-04-01 04:25:00 35.0 25.0 x w
2013-04-01 04:25:00 35.0 25.0 z u
2013-04-01 04:30:00 5.0 30.0 y u
2013-04-01 04:35:00 10.0 5.0 y w
2013-04-01 04:40:00 15.0 10.0 z w
2013-04-01 04:40:00 15.0 10.0 x u
2013-04-01 04:40:00 15.0 10.0 y v
2013-04-01 04:50:00 10.0 20.0 x w
主要問題是整個數據幀有超過200萬行,因此使用循環太耗時。 有沒有辦法實現這個問題的矢量化方法?
數據幀的python代碼如下:
d = {'Date': ['2013-04-01 03:50:00','2013-04-01 04:00:00','2013-04-01
04:15:00','2013-04-01 04:25:00','2013-04-01 04:25:00',
'2013-04-01 04:30:00','2013-04-01 04:35:00','2013-04-01 04:40:00','2013-04-01 04:40:00','2013-04-01 04:40:00',
'2013-04-01 04:50:00'], 'indicator_1': ['x','y','z','x','z','y','y','z','x','y','x'],
'indicator_2': ['w','u','v','w','u','u','w','w','u','v','w'],
'desired_column_1': [np.nan, 10, 25, 35, 35,5,10,15,15,15,10],
'desired_column_2': [np.nan, np.nan, 15, 25, 25,30,5,10,10,10,20]}
df = pd.DataFrame(data=d)
首先確保列['Date']
是一個datetime對象,並獲取一列來表示行與行之間的時間差
df.Date = pd.to_datetime(df.Date)
df['minD'] = (df.Date -df.Date.shift(1)).astype('timedelta64[m]')
接下來為您的條件創建分組鍵。 我們向下移動一行,因為我們正在尋找自上一個x以來的時間,這也包括下一個x值。 如果沒有轉移,我們就不會在我們的小組中包含下一個x。
mask2 = (df.indicator_1.str.cat(df.indicator_2) == 'yu').cumsum().shift(1)
mask1 = (df.indicator_1 == 'x').cumsum().shift(1)
現在通過mask和cumsum()
微小差異,但是我們需要過濾出布爾值的cumsum()
<1,因為條件還沒有發生,因此應該有時間差的缺失值。
df['desired_column_1'] = df.groupby(mask1.where(mask1 > 0)).minD.cumsum()
df['desired_column_2'] = df.groupby(mask2.where(mask2 > 0)).minD.cumsum()
現在,您可以通過向前填充數據來替換這些列中的0值
df.desired_column_1 = df.desired_column_1.replace(0,method='ffill')
df.desired_column_2 = df.desired_column_2.replace(0,method='ffill')
這個
Date indicator_1 indicator_2 desired_column_1 \
0 2013-04-01 03:50:00 x w NaN
1 2013-04-01 04:00:00 y u 10.0
2 2013-04-01 04:15:00 z v 25.0
3 2013-04-01 04:25:00 x w 35.0
4 2013-04-01 04:25:00 z u 35.0
5 2013-04-01 04:30:00 y u 5.0
6 2013-04-01 04:35:00 y w 10.0
7 2013-04-01 04:40:00 z w 15.0
8 2013-04-01 04:40:00 x u 15.0
9 2013-04-01 04:40:00 y v 15.0
10 2013-04-01 04:50:00 x w 10.0
desired_column_2
0 NaN
1 NaN
2 15.0
3 25.0
4 25.0
5 30.0
6 5.0
7 10.0
8 10.0
df = df.loc[:, ['Date', 'indicator_1', 'indicator_2']]
idx = df.index
df['Date'] = df['Date'].apply(pd.to_datetime)
# Sort by column indicator_1 for using df.diff()
df.sort_values(['indicator_1'], inplace=True)
df['diffs1'] = df['Date'].diff()
# Shift 1 then compare with original to get the line that value changes (from x to y for init)
mask = df.indicator_1 != df.indicator_1.shift(1)
df['diffs1'][mask] = np.nan
df.reindex(idx)
# Same for case 2
df['indicator_3'] = df['indicator_1'] + df['indicator_2']
df.sort_values(['indicator_3'], inplace=True)
df['diffs2'] = df['Date'].diff()
mask = df.indicator_3 != df.indicator_3.shift(1)
df['diffs2'][mask] = np.nan
df.reindex(idx)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.