【问题标题】:Pandas groupby mark dates less than n monthsPandas groupby 标记日期小于 n 个月
【发布时间】:2019-10-05 15:03:59
【问题描述】:

所以在这个例子中,col1 有 2 个不同的类别。如果我们说 n 个月 = 12,那么如何计算那些满足的类别,以便新列将类别 A 标记为 True,但将 cat B 标记为 false,因为它大于 n=12 个月。

d_ex = pd.DataFrame({'col1': ['A', 'A', 'B', 'B', 'A'],
                     'col2': ['2019-01-01', '2018-02-01',
                             '2015-01-01', '2019-01-01', '2019-05-01']})

d_ex['col2'] = pd.to_datetime(d_ex['col2'])

我试过了

d_ex.groupby(['col1'])['col2'].diff()

但这不起作用。该类别也可能有超过两次出现,因此如果有第三个类别 A 的日期为 2015 年,我希望将其标记为 False,但其他两个仍然正确。

我找到了这个,但我不确定如何将代码更改为不使用 idxmax Calculating the difference in dates in a Pandas GroupBy object

尝试给出的解决方案

(d_ex.groupby('col1')['col2'].diff().apply(lambda x: my_abs(x))
.apply(lambda x: set_condition(x)).bfill())

返回

0     True
1     True
2    False
3    False
4    False

但索引 4 应该是 True

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    创建数据框:

    import pandas as pd
    
    d_ex = pd.DataFrame({'col1': ['A', 'A', 'B', 'B', 'A'],
                         'col2': ['2019-01-01', '2018-02-01',
                                  '2015-01-01', '2019-01-01', '2019-05-01']})
    
    d_ex['col2'] = pd.to_datetime(d_ex['col2'])
    
    # Sort the columns
    d_ex.sort_values(['col1', 'col2'], inplace=True)
    
    col1       col2
       A 2018-02-01
       A 2019-01-01
       A 2019-05-01
       B 2015-01-01
       B 2019-01-01
    

    Groupby 差异:

    • diff 为每个组返回一个 timedelta 对象
      • NaT 总是在组内第一次出现
    d_ex['diff'] = d_ex.groupby('col1').diff()
    
    col1       col2      diff
       A 2018-02-01       NaT
       A 2019-01-01  334 days
       A 2019-05-01  120 days
       B 2015-01-01       NaT
       B 2019-01-01 1461 days
    

    返回差异abs的函数

    • abs不适用于NaT,所以abs不能随便应用
    • 如果你在col1col2上使用sort_values,这一步可以跳过
    def my_abs(x):
        try:
            x = abs(x)
        except TypeError:
            x = x
        return x
    
    # Apply the function
    d_ex['diff'] = d_ex['diff'].apply(lambda x: my_abs(x))
    
    col1       col2      diff
       A 2018-02-01       NaT
       A 2019-01-01  334 days
       A 2019-05-01  120 days
       B 2015-01-01       NaT
       B 2019-01-01 1461 days
    

    设置条件的函数,如果是 NaT 则为 None

    • 因为使用groupbydiff,所以任何组的第一行都应该是NaT
    • NaT设置为None,则可以是backfilled
    def set_condition(x):
        if type(x) == pd._libs.tslibs.nattype.NaTType:
            x = None
        elif x <= pd.Timedelta('365 days'):
            x = True
        else:
            x = False
        return x
    
    # Apply the function
    d_ex['condition'] = d_ex['diff'].apply(lambda x: set_condition(x))
    
    col1       col2      diff condition
       A 2018-02-01       NaT      None
       A 2019-01-01  334 days      True
       A 2019-05-01  120 days      True
       B 2015-01-01       NaT      None
       B 2019-01-01 1461 days     False
    

    回填无:

    d_ex.condition.bfill(inplace=True)
    
    col1       col2      diff  condition
       A 2018-02-01       NaT       True
       A 2019-01-01  334 days       True
       A 2019-05-01  120 days       True
       B 2015-01-01       NaT      False
       B 2019-01-01 1461 days      False
    

    【讨论】:

    • @bbd108 答案已更新为对col1col2 进行排序。这也消除了使用my_abs的需要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 2018-10-26
    • 2019-07-02
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多