【问题标题】:pandas filter by datetime after grouby大熊猫在grouby之后按日期时间过滤
【发布时间】:2021-02-10 22:54:58
【问题描述】:

在按特定列对数据框进行分组后,我想选择分组列的每个键的最后一个值之前的前六个月的日期。 例如,在这个数据框中

df = pd.DataFrame([
  {'id': 'thing 1', 'date': '2016-01-01', 'quantity': 1 },
  {'id': 'thing 1', 'date': '2016-02-01', 'quantity': 1 },
  {'id': 'thing 1', 'date': '2016-09-01', 'quantity': 1 },
  {'id': 'thing 1', 'date': '2016-10-01', 'quantity': 1 },
  {'id': 'thing 2', 'date': '2017-01-01', 'quantity': 2 },
  {'id': 'thing 2', 'date': '2017-02-01', 'quantity': 2 },
  {'id': 'thing 2', 'date': '2017-02-11', 'quantity': 2 },
  {'id': 'thing 2', 'date': '2017-09-01', 'quantity': 2 },
  {'id': 'thing 2', 'date': '2017-10-01', 'quantity': 2 },
])
df.date = pd.to_datetime(df.date, format="%Y-%m-%d")
df

我想选择thing 1的前2行和thing 2的前3行。

我可以找到每个id 的开始和结束日期:

df.groupby('id').date.max()-pd.DateOffset(years=1)
df.groupby('id').date.max()-pd.DateOffset(months=6)

但我找不到选择中间日期的方法。


我最好的(也是幼稚的)尝试如下:

df[(df.groupby('id').date>(df.groupby('id').date.max()-pd.DateOffset(years=1))) & (df.groupby('id').date<(df.groupby('id').date.max()-pd.DateOffset(months=6)))]

返回是可以理解的

TypeError:dtype=datetime64[ns] 和 SeriesGroupBy 之间的比较无效

【问题讨论】:

    标签: python pandas datetime pandas-groupby


    【解决方案1】:

    您可以使用groupby.transform 并获取每行的最高日期。然后我们用pd.DateOffset减去6个月,最后用Series.lt与代表less than的每一行进行比较,与&lt;相同:

    max_date = df.groupby('id')['date'].transform('max') - pd.DateOffset(months=6)
    df[df['date'].lt(max_date)]
    # or df[df['date'] < max_date]
    

    输出

            id       date  quantity
    0  thing 1 2016-01-01         1
    1  thing 1 2016-02-01         1
    4  thing 2 2017-01-01         2
    5  thing 2 2017-02-01         2
    6  thing 2 2017-02-11         2
    

    【讨论】:

    • 当我运行它时,我得到“dtype=float64 和 Timestamp 之间的无效比较”......但这似乎是正确的方法!一个警告是我还必须指定一个 min_date;我想我可以做到.gt(min_date)?
    • 确保您的列都是datetime 类型。是的,首先制作一个 min_date 系列。如果您需要任何帮助,请告诉我。
    • 我设法做到了,但用两行代码df=df[df['date'].lt(max_date)]' and df=df[df['date'].gt(min_date)]' 其中min_date = df.groupby('id')['date'].transform('max') - pd.DateOffset(years=1)。有没有一种行得通的?我在尝试df[(df['date'].lt(max_date)) and (df[df['date'].gt(min_date)])]的一些变体时遇到了一大堆错误@
    • Pandas 使用&amp; 作为逻辑运算符,所以这样做:df[df['date'].lt(max_date) &amp; df['date'].gt(min_date)]
    • 啊!对...但现在我得到The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
    【解决方案2】:

    这可能是一种愚蠢的方法,但是...您可以根据现有日期在月份的 df 中添加一个新列。

    df['MONTH'] = pd.DatetimeIndex(df['date']).month
    

    它将在 1 月 1 日、2 月 2 日等

    然后在前六个月过滤掉该列,其中 |表示或

    df = df.loc[df['MONTH'] == 1]|[df['MONTH'] == 2]|[df['MONTH'] == 3]|[df['MONTH'] == 4]|[df['MONTH'] == 5]|[df['MONTH'] == 6]|
    

    【讨论】:

    • 一个简洁的方法:df.loc[df.date.dt.month.between(1,6)]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2022-11-04
    • 2019-02-25
    • 2020-10-19
    • 2016-05-05
    • 1970-01-01
    相关资源
    最近更新 更多