【问题标题】:Updating pandas row value where ids match, and timestamp is greater than previous records更新 id 匹配且时间戳大于先前记录的 pandas 行值
【发布时间】:2022-01-21 08:43:03
【问题描述】:

我有一个遵循这种结构的数据框:

             id          created_at  seen_before
0          1043 2021-11-27 16:56:43            0
1          1027 2021-11-22 19:01:21            0
2          1099 2021-11-22 07:37:02            0
3          1099 2021-11-22 07:36:50            0
4          1099 2021-11-22 07:36:41            0
5          1027 2021-11-22 07:36:39            0

我想查看每一行,并检查是否存在具有较早时间戳的匹配 id,并在 seen_before 列中用 1 指示它,以便更新数据框像这样:

             id          created_at  seen_before
0          1043 2021-11-27 16:56:43            0
1          1027 2021-11-22 19:01:21            1
2          1099 2021-11-22 07:37:02            1
3          1099 2021-11-22 07:36:50            1
4          1099 2021-11-22 07:36:41            0
5          1027 2021-11-22 07:36:39            0

我已经制定了一个迭代每一行的解决方案,并将该行与数据帧的其余部分进行比较:

for _, row in df.iterrows():
      df.loc[(df['created_at'] > row['created_at']) & (df['id'] == row['id']), 'seen_before'] = 1

这行得通,但它似乎不是很有可扩展性,因为我正在处理大量数据,并且希望避免遍历每一行。

如果 pandas 中存在更具可扩展性的方法,我想知道。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以groupby "id" 和 "created_at" 找到 min 并将其转换为整个 DataFrame。然后将其与原始的“created_at”日期时间进行比较,以查看是否有任何日期时间在使用lt 的最小日期时间之后;这将创建一个布尔系列,其中对于每个“id”,该“id”的最早日期时间之后的任何日期时间都将评估为 True => 将其转换为 dtype int 以获得最终输出。

    df['created_at'] = pd.to_datetime(df['created_at'])
    df['seen_before'] = df.groupby('id')['created_at'].transform('min').lt(df['created_at']).astype(int)
    

    输出:

         id          created_at  seen_before
    0  1043 2021-11-27 16:56:43            0
    1  1027 2021-11-22 19:01:21            1
    2  1099 2021-11-22 07:37:02            1
    3  1099 2021-11-22 07:36:50            1
    4  1099 2021-11-22 07:36:41            0
    5  1027 2021-11-22 07:36:39            0
    

    【讨论】:

      【解决方案2】:

      你可以使用 lambda 函数:

      df['seen']  = df.apply(lambda row: 1 if row['created_at'] > min(df['created_at'].loc[df['id'] == row['id']])  else 0, axis = 1)
      

      结果:

      
          id      created_at          seen
      0   1043    2021-11-27 16:56:43 0
      1   1027    2021-11-22 19:01:21 1
      2   1099    2021-11-22 07:37:02 1
      3   1099    2021-11-22 07:36:50 1
      4   1099    2021-11-22 07:36:41 0
      5   1027    2021-11-22 07:36:39 0
      

      【讨论】:

        【解决方案3】:

        由于您的created_at 列按降序排序,您可以简单地使用:

        df['seen_before'] = df.duplicated('id', keep='last').astype(int)
        print(df)
        
        # Output
             id          created_at  seen_before
        0  1043 2021-11-27 16:56:43            0
        1  1027 2021-11-22 19:01:21            1
        2  1099 2021-11-22 07:37:02            1
        3  1099 2021-11-22 07:36:50            1
        4  1099 2021-11-22 07:36:41            0
        5  1027 2021-11-22 07:36:39            0
        

        【讨论】:

          猜你喜欢
          • 2021-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-07
          • 2020-09-30
          • 2021-12-21
          • 2017-03-06
          • 2014-12-19
          相关资源
          最近更新 更多