【问题标题】:Complex group by using Pandas使用 Pandas 的复杂组
【发布时间】:2020-05-15 23:09:35
【问题描述】:

我面临的情况是,我需要按“ID”列对数据帧进行分组,并计算为完成该特定 ID 描述的总时间范围。我只想计算具有 ID 计数的特定 ID 的 date_open 和 data_close 之间的差异。 我们只需要关注打开日期和关闭日期字段。所以它需要做一些事情,取最大关闭日期和最小打开日期并减去两者 数据框如下所示:

ID      Date_Open     Date_Closed
1       01/01/2019     02/01/2019
1       07/01/2019     09/01/2019
2       10/01/2019     11/01/2019
2       13/01/2019     19/01/2019
3       10/01/2019     11/01/2019

输出应该是这样的:

ID     Count_of_ID     Total_Time_In_Days
1         2                8
2         2                9
3         1                1

我应该如何做到这一点?

【问题讨论】:

  • 请展示自己解决问题的努力(提供MCVE)并可能提出更具体的问题。

标签: python-3.x pandas pivot-table pandas-groupby


【解决方案1】:

GroupBy 与named_aggregation 以及日期的minmax 一起使用:

df[['Date_Open', 'Date_Closed']] = (
    df[['Date_Open', 'Date_Closed']].apply(lambda x: pd.to_datetime(x, format='%d/%m/%Y'))
)

dfg = df.groupby('ID').agg(
    Count_of_ID=('ID','size'),
    Date_Open=('Date_Open','min'),
    Date_Closed=('Date_Closed','max')
)

dfg['Total_Time_In_Days'] = dfg['Date_Closed'].sub(dfg['Date_Open']).dt.days
dfg = dfg.drop(columns=['Date_Closed', 'Date_Open']).reset_index()
   ID  Count_of_ID  Total_Time_In_Days
0   1            2                   8
1   2            2                   9
2   3            1                   1

现在我们将Total_Time_In_Days 设为int

print(dfg.dtypes)

ID                    int64
Count_of_ID           int64
Total_Time_In_Days    int64
dtype: object

【讨论】:

  • 这正是我想要的!谢谢!
  • 只是出于好奇,最后一栏的“天”字是怎么来的?
  • 这就是timedelta 的表示方式,例如,如果您想要秒,请使用(dfg['Date_Closed'] - dfg['Date_Open']).dt.total_seconds()
  • 只看到数字而没有天数或秒数,应该怎么做?我只希望最后一列是 int 类型。我应该直接输入吗?
  • 第一行是否正确转换为日期时间。您必须确保您在示例中提供的日期格式与您的数据中的相同。现在在我的回答中,我假设:%d/%m/%Y 这是dd/mm/yyyy
【解决方案2】:

这个也可以用:

df['Date_Open'] =  pd.to_datetime(df['Date_Open'], dayfirst=True)
df['Date_Closed'] =  pd.to_datetime(df['Date_Closed'], dayfirst=True)
df_grouped = df.groupby(by='ID').count()
df_grouped['Total_Time_In_Days'] = df.groupby(by='ID')['Date_Closed'].max() - df.groupby(by='ID')['Date_Open'].min()
df_grouped = df_grouped.drop(columns=['Date_Open'])
df_grouped.columns=['Count', 'Total_Time_In_Days']
print(df_grouped)


     Count  Total_Time_In_Days
ID      
1      2    8 days
2      2    9 days
3      1    1 days

【讨论】:

    【解决方案3】:

    我将首先尝试创建一个列来描述数据框的每个实例从 Date_open 到 Date_close 所经过的时间。像这样:

    df['Total_Time_In_Days'] = df.Date_closed - df.Date_open
    

    那么就可以使用groupby了:

    df.groupby('id').agg({'id':'count','Total_Time_In_Days':'sum'})
    

    如果您需要任何关于 .agg 功能的帮助,您可以参考它的官方文档here

    【讨论】:

    • 这不是他想要的,他在寻找每个 ID 的 max(Date_closed) - min(Date_open),而不是每一行。
    猜你喜欢
    • 2021-12-03
    • 1970-01-01
    • 2020-09-19
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2016-11-17
    • 1970-01-01
    相关资源
    最近更新 更多