Pandas Dataframe -将两列的值与前一行进行比较以创建新列

nwnhqdif  于 2023-06-20  发布在  其他
关注(0)|答案(2)|浏览(197)

我正在检查一个事件是否发生在同一天的多个日期和地点。在简化表中有一个日期列、一个位置列和一个事件列。我需要创建一个名为“事件检查”的新专栏。EVENTCHECK应该将当前行中的DATE与上面的所有行进行比较,如果匹配,则检查该日期行上的事件列是否为1,并返回1。
下面是虚拟数据表:

import pandas as pd

df = pd.DataFrame()
df['DATE'] = ['2022-01-01','2022-01-02','2022-01-03','2022-01-04','2022-01-05','2022-01-01','2022-01-02','2022-01-03','2022-01-04','2022-01-05']
df['LOCATION'] = ['A','A','A','A','A','B','B','B','B','B']
df['EVENT'] = [1,1,1,1,1,0,0,0,0,0]

EVENTCHECK列中的正确结果应为True。我试过下面的方法,也试过使用掩码,但不知道如何将当前行与日期列中的前一行进行比较。任何帮助都是真诚的感谢。

import pandas as pd

df = pd.DataFrame()
df['DATE'] = ['2022-01-01','2022-01-02','2022-01-03','2022-01-04','2022-01-05','2022-01-01','2022-01-02','2022-01-03','2022-01-04','2022-01-05']
df['LOCATION'] = ['A','A','A','A','A','B','B','B','B','B']
df['EVENT'] = [1,1,1,1,1,0,0,0,0,0]

df['EVENT_CHECK'] = (df['DATE'].isin(df['DATE'])) & (df['EVENT'] == 1)
print(df)
polhcujo

polhcujo1#

如果这些值等于所有先前值,则当前值等于第一个值,并且没有先前值不不同。
然后,您可以使用groupby.transform('first')进行比较,然后使用groupby.cummin

df['EVENT_CHECK'] = (df['EVENT'].eq(df.groupby('LOCATION')['EVENT']
                                      .transform('first'))
                     .groupby(df['LOCATION']).cummin()
                    )

groupby.apply相同的逻辑:

df['EVENT_CHECK'] = (df.groupby('LOCATION', group_keys=False)
                       .apply(lambda g: g['EVENT'].eq(g['EVENT'].iloc[0])
                                         .cummin())
                     )
  • 注:这假设日期最初是排序的。如果没有,首先添加.sort_values(by=['LOCATION', 'DATE'])作为预备步骤。
只有1个重要

如果你只对1感兴趣,那么你可以简化为:

df['EVENT_CHECK'] = df['EVENT'].eq(1).groupby(df['LOCATION']).cummin()

输出:

DATE LOCATION  EVENT  EVENT_CHECK
0  2022-01-01        A      1         True
1  2022-01-02        A      1         True
2  2022-01-03        A      1         True
3  2022-01-04        A      1         True
4  2022-01-05        A      1         True
5  2022-01-01        B      0         True
6  2022-01-02        B      0         True
7  2022-01-03        B      0         True
8  2022-01-04        B      0         True
9  2022-01-05        B      0         True
更有意义的示例:
DATE LOCATION  EVENT  EVENT_CHECK
0  2022-01-01        A      1         True
1  2022-01-02        A      1         True
2  2022-01-03        A      2        False  # 2 ≠ 1
3  2022-01-04        A      1        False  # 1 not equal to all previous
4  2022-01-05        A      1        False
5  2022-01-01        B      0         True
6  2022-01-02        B      0         True
7  2022-01-03        B      0         True
8  2022-01-04        B      0         True
9  2022-01-05        B      0         True
替代

为了好玩,如果日期对所有地点都是通用的,这里有一个重塑和merge的替代方案:

out = df.merge(
 df.pivot(index='DATE', columns='LOCATION', values='EVENT')
   .pipe(lambda d: d.eq(d.iloc[0]).cummin())
   .stack().rename('EVENT_CHECK'),
 left_on=['DATE', 'LOCATION'], right_index=True
)
k5ifujac

k5ifujac2#

如果你想以最有效的方式(矢量化)来实现,你可以这样做:

df['EVENT_CHECK'] = df.groupby('DATE')['EVENT'].transform('sum').ge(1)

输出(我添加了额外的非事件日期):

DATE    LOCATION    EVENT   EVENT_CHECK
0   2022-01-01  A         1     True
1   2022-01-02  A         1     True
2   2022-01-03  A         1     True
3   2022-01-04  A         1     True
4   2022-01-05  A         1     True
5   2022-01-01  B         0     True
6   2022-01-02  B         0     True
7   2022-01-03  B         0     True
8   2022-01-04  B         0     True
9   2022-01-05  B         0     True
10  2025-01-06  B         0     False

相关问题