【问题标题】:pandas groupby apply with condition on the first occurrence of a column valuepandas groupby 在第一次出现列值时应用条件
【发布时间】:2021-11-22 01:57:54
【问题描述】:

我有一个如下所示的数据框,其中pidevent_date 是应用groupby 后的索引。这次我想再次申请groupby,只申请pid,适用于两个条件:

  1. 一个人 (pid=person) 有两个或多个 True 标签;
  2. 此人的第一个真实实例发生在他/她未满 45 岁;

如果满足上述两个条件,则在 groupby-ed 数据帧中将此人/pid 分配为 True。

                           age      label
  pid       event_date      
00000001    2000-08-28  76.334247   False
            2000-10-17  76.471233   False
            2000-10-31  76.509589   True
            2000-11-02  76.512329   True
... ... ... ...
00000005    2014-08-15  42.769863   False
            2015-04-04  43.476712   False
            2015-11-06  44.057534   True
            2017-03-06  45.386301   True

到目前为止,我只是为了实现第一个条件:

df = (df.groupby(['pid']).apply(lambda x: sum(x['label'])>1).to_frame('label'))

第二个对我来说很棘手。如何以某些列值的第一次出现为条件?非常欢迎任何建议!非常感谢!

使用示例数据框更新:

a = pd.DataFrame(columns=['pid', 'event_date', 'age', 'label'])
a['pid'] = [1, 1, 1, 1, 5, 5, 5, 5]
a['event_date'] = ['2000-08-28', '2000-08-28', '2000-08-28', '2000-08-28',\
                  '2000-08-28', '2000-08-28', '2000-08-28', '2000-08-28']
a['event_date'] = pd.to_datetime(a.event_date)
a['age'] = [76.334247, 76.471233, 76.509589, 76.512329, 42.769863, 43.476712, 44.057534, 45.386301]
a['label'] = [False, False, True, True, False, False, True, True]

a = (a.groupby(['pid', 'event_date', 'age']).apply(lambda x: x['label'].any()).to_frame('label'))
a.reset_index(level=['age'], inplace=True)

现在如果我申请 (a.groupby(['pid']).apply(lambda x: sum(x['label'])>1).to_frame('label')) 我会得到

    label
pid 
1   True
5   True

仅满足第一个条件(好吧,因为我跳过了第二个条件)。添加第二个条件应该只标记pid=5 True,因为当第一个label=True 发生时,只有这个人/pid 在 45 岁以下。

【问题讨论】:

  • 什么是“人”?你说“一个人有两个或多个 True 标签”,但你怎么知道 N 个 True 标签是否属于同一个人?
  • pid = "人";很抱歉造成混乱!
  • 这可以实现,因为数据框已经有pid作为索引列
  • “达到”,抱歉
  • 非常感谢!我现在在更新的问题中添加了一个示例数据框!

标签: python pandas pandas-groupby


【解决方案1】:

半(有趣)小时后,我想出了这个:

condition = a.reset_index().groupby('pid')['label'].sum().ge(2) & a.reset_index().groupby('pid').apply(lambda x: x['age'][x['label'].idxmax()] < 45)

输出:

>>> condition
pid
1    False
5     True
dtype: bool

如果索引正常,而不是 pid + event_date 的 MultiIndex,它可能会缩短一点(删除两个 .reset_index() 调用)。如果您从一开始就无法避免这种情况,并且您不介意更改a

a = a.reset_index()
condition = a.groupby('pid')['label'].sum().ge(2) & a.groupby('pid').apply(lambda x: x['age'][x['label'].idxmax()] < 45)

扩展:

condition = (
    a.groupby('pid') # Group by pid
    ['label']        # Get the label column for each group
    .sum()           # Compute the sum of the True values
    .ge(2)           # Are there two or more?
    
    & # Boolean mask. The previous and the next bits of code are the two conditions, and they return a series, where the index is each unique pid, and the value is whether the condition is met for all the rows in that pid
    
    a.groupby('pid')                # Group by pid
    .apply(                         # Call a function for each group, passing the group (a dataframe) to the function as its first parameter
        lambda x:                   # Function start
            x['age'][               # Get item from the age column at the specified index
                x['label'].idxmax() # Get the index of the highest value of the label column (since they're only boolean values, the highest will be the first True value)
            ] < 45                  # Check if it's less than 45
    )
)

【讨论】:

    猜你喜欢
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-05
    • 2016-01-21
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多