Pandas从不同列查找值

时间:2014-07-17 15:24:21

标签: python pandas

我正在寻找解决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

4 个答案:

答案 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