【问题标题】:Maximum of the DataFrame column based on the conditions relative to the same DataFrame基于相对于同一 DataFrame 的条件的 DataFrame 列的最大值
【发布时间】:2020-09-15 12:15:48
【问题描述】:

我有一个如下所示的 DataFrame:

CUSTOMER_ID MONTH       ACTIVE
123456      2020-01     1
123456      2020-02     0
123456      2020-03     0
123456      2020-04     1
654321      2020-01     1
654321      2020-02     1
654321      2020-03     0
654321      2020-04     0

根据这些数据,对于每一行(代表特定客户在该月的表现),我需要添加该特定客户上次活跃的 MONTH,相对于该行的 MONTH。

对于此处的示例数据子集而言,理想情况下,DataFrame 应如下所示:

CUSTOMER_ID MONTH       ACTIVE      LAST_TIME_ACTIVE
123456      2020-01     1               2020-01
123456      2020-02     0               2020-01
123456      2020-03     0               2020-01
123456      2020-04     1               2020-04
654321      2020-01     1               2020-01
654321      2020-02     1               2020-02
654321      2020-03     0               2020-02
654321      2020-04     0               2020-02

我尝试了this link 上解释的解决方案,但那里的解决方案会给我一般最大值,它不满足“相对于该行的月份”条件。

除此之外,我尝试定义函数并使用 .apply() 从我的 DataFrame 调用它,但它非常慢,因为每次过滤整个 DataFrame - 这是所有操作中成本最高的操作。

函数的定义如下:

def get_last_active_month(dfRow, wholeDF) :
    
    try:
        lastActiveMonth = wholeDF[(wholeDF['CUSTOMER_ID']==dfRow['CUSTOMER_ID']) & (wholeDF['MONTH']<=dfRow['MONTH']) & (wholeDF['ACTIVE']==1)]['MONTH'].item()
    except:
        lastActiveMonth = '2017-12'
    finally:
        return lastActiveMonth;

我正在与超过 90,000 名客户合作,我需要将这个逻辑应用于从 2018 年开始一直到今天的数据,所以我们正在讨论很多行。当然,循环是不可能的(我什至尝试过这是一种绝望的行为,当然它非常慢,而且是非 Pythonic 的“解决方案”)。

在寻找 Pythonic 和快速解决方案方面,我很乐意寻求帮助。谢谢!

【问题讨论】:

    标签: python pandas dataframe filter max


    【解决方案1】:

    pd.Series.wheregroupbyffill 一起使用:

    df["new"] = df["MONTH"].where(df["ACTIVE"].ne(0))
    
    df["new"] = df.groupby("CUSTOMER_ID")["new"].ffill()
    
    print (df)
    
       CUSTOMER_ID    MONTH  ACTIVE      new
    0       123456  2020-01       1  2020-01
    1       123456  2020-02       0  2020-01
    2       123456  2020-03       0  2020-01
    3       123456  2020-04       1  2020-04
    4       654321  2020-01       1  2020-01
    5       654321  2020-02       1  2020-02
    6       654321  2020-03       0  2020-02
    7       654321  2020-04       0  2020-02
    

    【讨论】:

    • 非常感谢!它适用于我正在测试我的代码的小数据集。我现在将对所有数据进行测试,然后回来接受解决方案。
    【解决方案2】:

    Pandas 一个(混淆的)班轮(假设使用 Date 类型):

    df['month_last_active'] = df.groupby([df.CUSTOMER_ID, df.groupby('CUSTOMER_ID').ACTIVE.cumsum()]).MONTH.cummin()
    

    【讨论】:

    • 谢谢!不幸的是,数据类型是 str,因为我们的计费月份并不总是真实世界的月份,而是与我们的内部业务逻辑相关联,这使得我们甚至在某些年份也有超过 20 个月 :) 我无法测试解决方案我的数据,但我相信它很有用!
    • 不用担心,请注意您可以df['MONTH'] = pd.to_datetime(df['MONTH']) 强制在应用一个衬里之前的日期(使其成为两个衬里)
    • @3MAJ86 如果你觉得我的解决方案有用,别忘了点赞 ;) !
    • 我投了赞成票,虽然我是这里的新用户,但我的赞成票不可见 :(
    猜你喜欢
    • 2020-10-16
    • 2016-03-22
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多