我正在寻找解决Pandas中以下问题的最佳方法。给定数据帧df
,例如
import pandas as pd
dt = pd.date_range('1/1/2014', periods=10, freq='H')
df = pd.DataFrame({'A':[0.,0.,0.,1.,0.,0.,1.,0.,0.,0.],'B':[0.,0.,0.,0.,1.,0.,0.,0.,0.,1.]},index=dt)
df
A B
2014-01-01 00:00:00 0 0
2014-01-01 01:00:00 0 0
2014-01-01 02:00:00 0 0
2014-01-01 03:00:00 1 0
2014-01-01 04:00:00 0 1
2014-01-01 05:00:00 0 0
2014-01-01 06:00:00 1 0
2014-01-01 07:00:00 0 0
2014-01-01 08:00:00 0 0
2014-01-01 09:00:00 0 1
然后对于B=1
的每一行,我想找到A=1
之前的最后一行的索引,即
A B C
2014-01-01 04:00:00 0 1 2014-01-01 03:00:00
2014-01-01 09:00:00 0 1 2014-01-01 06:00:00
不确定在Pandas上执行此操作的最简单方法是什么,同时对大型数据帧也相当有效。
更新:
我应该在原来的问题中明确表示,我希望每个A=1
可能有多个B=1
。
答案 0 :(得分:1)
这是一个想法 - 可能会有更好的东西。
使用索引值填充列C
,其中A
为1。
df['C'] = np.where(df['A'] == 1, df.index, '')
转发填写缺失值,因此它表示上次A
为1。
df['C'] = df['C'].fillna(method='ffill')
最后,填写B
不为1且缺少值的所有值。
df['C'] = np.where(df['B'] == 1, df['C'], '')
In [108]: df
Out[108]:
A B C
2014-01-01 00:00:00 0 0 NaT
2014-01-01 01:00:00 0 0 NaT
2014-01-01 02:00:00 0 0 NaT
2014-01-01 03:00:00 1 0 NaT
2014-01-01 04:00:00 0 1 2014-01-01 03:00:00
2014-01-01 05:00:00 0 0 NaT
2014-01-01 06:00:00 1 0 NaT
2014-01-01 07:00:00 0 0 NaT
2014-01-01 08:00:00 0 0 NaT
2014-01-01 09:00:00 0 1 2014-01-01 06:00:00
答案 1 :(得分:1)
请注意,如果每个A
拆分组的值超过B
,则@jeanrjc的答案不稳定。为了表明这一点,我操纵了给定的数据帧:
In[217]: df.iloc[2]['A'] = 1
In[218]: df
Out[218]:
A B
2014-01-01 00:00:00 0 0
2014-01-01 01:00:00 0 0
2014-01-01 02:00:00 1 0
2014-01-01 03:00:00 1 0
2014-01-01 04:00:00 0 1
2014-01-01 05:00:00 0 0
2014-01-01 06:00:00 1 0
2014-01-01 07:00:00 0 0
2014-01-01 08:00:00 0 0
2014-01-01 09:00:00 0 1
他继续从df.A == 1
处获取时间戳 - 如果每个子组发生多次,则表示您有错误。
In[219]: new_df["C"] = df.index[np.where(df.A==1)[0]]
Traceback (...)
ValueError: Length of values does not match length of index
相反,我创建了一个收集正确索引的数组。如果你想了解发生了什么,试着从外面理解它(首先,df.loc[:b]
给出我的for循环,然后是下一个子选择等。)
In[239]: new_df['C'] = [df.loc[:b][df.loc[:b].A == 1].iloc[-1].name for b in df.loc[df.B == 1].index ]
In[240]: new_df
Out[240]:
A B C
2014-01-01 04:00:00 0 1 2014-01-01 03:00:00
2014-01-01 09:00:00 0 1 2014-01-01 06:00:00
答案 2 :(得分:0)
我会这样做:
new_df = df[df.B==1]
new_df["C"] = df.index[np.where(df.A==1)[0]]
new_df
A B C
2014-01-01 04:00:00 0 1 2014-01-01 03:00:00
2014-01-01 09:00:00 0 1 2014-01-01 06:00:00
答案 3 :(得分:0)
这就是我要做的。易于理解和阅读
import pandas as pd
dt = pd.date_range('1/1/2014', periods=10, freq='H')
df = pd.DataFrame({'A':[0.,0.,0.,1.,0.,0.,1.,0.,0.,0.],
'B':[0.,0.,0.,0.,1.,0.,0.,0.,0.,1.]},
index=dt)
# How I would do it
temp = np.where(df['B']==1)[0]
newdf = df.iloc[temp]
temp2 = np.where(df['A']==1)[0]
newdf['C'] = df.iloc[temp2].index
打印
In [8]: newdf
Out[8]:
A B C
2014-01-01 04:00:00 0 1 2014-01-01 03:00:00
2014-01-01 09:00:00 0 1 2014-01-01 08:00:00