【问题标题】:Keep max value until ID and condition change in Pandas保持最大值直到 Pandas 中的 ID 和条件发生变化
【发布时间】:2022-10-24 04:00:16
【问题描述】:

我有一个看起来像这样的数据框 (link to csv)

id       time        value   approved
  1       0:00        10       false
  1       0:01        20       true
  1       0:02        30       true
  1       0:03        20       true
  1       0:04        40       false
  1       0:05        35       false
  1       0:06        60       false
  2       0:07        20       true
  2       0:08        30       true
  2       0:09        50       false
  2       0:10        45       false
  2       0:11        70       false
  2       0:12        62       false

并且我想再创建两个列,以保持最大批准值的容差为 2 秒和相应最大值的时间。所以我希望它看起来像这样

id       time        value   approved    max_approved   max_time
  1       0:00        10       false         NaN          NaN
  1       0:01        20       true          20           0:01
  1       0:02        30       true          30           0:02
  1       0:03        20       true          30           0:02
  1       0:04        40       false         40           0:04
  1       0:05        35       false         40           0:04
  1       0:06        60       false         40           0:04
  2       0:07        20       true          20           0:07
  2       0:08        30       true          30           0:08
  2       0:09        50       false         50           0:09
  2       0:10        45       false         50           0:09
  2       0:11        70       false         50           0:09

我怎样才能做到这一点?谢谢

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    逻辑或输出并不完全清楚,但如果我猜对了,您可以尝试:

    df['td'] = pd.to_timedelta('0:'+df['time'])
    
    df[['max_approved', 'max_time']] = (df
       .assign(value=df['value'].where(df['approved']),
               last_time=lambda d: d['td'].dt.total_seconds().where(df['approved']),
              )
       .set_index('td').groupby('id')[['value', 'last_time']]
       .apply(lambda s: s.rolling('2s').max().ffill())
       .to_numpy()
    )
    

    输出:

        id  time  value  approved              td  max_approved  max_time
    0    1  0:00     10     False 0 days 00:00:00           NaN       NaN
    1    1  0:01     20      True 0 days 00:00:01          20.0       1.0
    2    1  0:02     30      True 0 days 00:00:02          30.0       2.0
    3    1  0:03     20      True 0 days 00:00:03          30.0       3.0
    4    1  0:04     40     False 0 days 00:00:04          20.0       3.0
    5    1  0:05     35     False 0 days 00:00:05          20.0       3.0
    6    1  0:06     60     False 0 days 00:00:06          20.0       3.0
    7    2  0:07     20      True 0 days 00:00:07          20.0       7.0
    8    2  0:08     30      True 0 days 00:00:08          30.0       8.0
    9    2  0:09     50     False 0 days 00:00:09          30.0       8.0
    10   2  0:10     45     False 0 days 00:00:10          30.0       8.0
    11   2  0:11     70     False 0 days 00:00:11          30.0       8.0
    12   2  0:12     62     False 0 days 00:00:12          30.0       8.0
    

    【讨论】:

    • 我认为您错过了计算助手td 的部分,对吗?请问可以加吗?谢谢
    • 非常感谢,这个解决方案完美!我对熊猫很陌生,你能评论@tturbo 提供的解决方案吗?据我所知,如果可以的话,应该避免使用iterrows(),所以你的解决方案更好,对吧?
    • 是的,它很慢。在我看来,当您别无选择时,应将iterrows 的使用限制在非常小的数据集上。我有时用它来绘制或生成小报告,几乎从不用于计算数据。除此之外,我无法评论 tturbo 的解决方案,因为它似乎不完整。
    • 实际上我只是意识到该解决方案不符合我的标准,可能我没有解释清楚。在max_time 上,我想保留max_approved 值的时间,所以在第3 行它应该是2.0,而不是更新到3.0。而且由于我仍然可以在批准变为假后 2 秒更新 max_approved 值,因此在第 4 行它应该将 max_approved 更新为 40 并将 max_time 更新为 4.0。你能更新你的答案以符合这个标准吗?谢谢
    • 嘿 Mozway,很抱歉再次打扰您,但我仍然不知道该怎么做,所以非常感谢您的帮助
    【解决方案2】:

    您可以使用iterrows 这样做

    max_value = 0
    for index, row_data in df.iterrows():
      # your logic, e.g.
      if row_data.approved and row_data.value > max_value:
        max_value = row_data.value
      df['max_approved'].iloc(index) = max_value
      ...
    

    这对开始有帮助吗?

    如果您想要一个确切的解决方案,请提供带有 DataFrame 的代码(这样我们就不必从您的问题中解析数据。或者您的代码以及您的问题在哪里

    【讨论】:

    • 我决定使用 mozway 的答案,因为它更完整和高效,但无论如何感谢您的帮助! :)
    【解决方案3】:

    经过几天的研究,我设法做到了:

    canBeTop = (df['approved'].rolling(window = 3, min_periods=1).max() == True)
    df['max_approved'] = df.groupby(['id', canBeTop])['value'].transform('cummax').where(canBeTop).ffill()
    df['max_time'] = df.where((canBeTop == True) & (df['value'] == df['max_approved']))['time']
    df['max_time'] = df.groupby('id', group_keys=False)['max_time'].apply(lambda x: x.ffill())
    

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 1970-01-01
      • 2018-11-23
      • 2015-09-16
      • 2022-01-22
      • 1970-01-01
      • 2021-12-23
      • 2012-12-26
      • 2022-11-22
      相关资源
      最近更新 更多