首页 > 解决方案 > Pandas 和 SQL 等效项(双重分组)

问题描述

我想计算当天持续时间总和超过 30 分钟(每个 ID)的天数

id      date              duration
111     2020-01-01        00:42:23
111     2020-01-01        00:23:23
111     2020-01-02        00:37:22
222     2020-01-02        00:13:08
222     2020-01-03        01:52:11
....
999     2020-01-31        00:15:21
999     2020-01-31        00:52:12

这是我用于计算的 SQL:

                    SELECT id, count(1)
                    FROM (
                        SELECT id
                        FROM statistic_prolonged
                        GROUP BY id, DAY(`date`)
                        HAVING SUM(TIMESTAMPDIFF(SECOND, date, date_end)) > 60 * 30
                    ) as t
                    GROUP BY id

这相当于熊猫:

df['duration'] = (df['date_end'] - df['date']).dt.seconds
total_activity = (
        df
        .groupby(['id', pd.Grouper(key='date', freq='D')])
        ['duration'].sum() > dt.timedelta(minutes=30).seconds
        .groupby('id')
        .sum()
        .astype(int)
)

print(len(total_activity))

但是我在相同的数据上得到了不同的结果。(Pandas 返回的行数比 SQL 多)

标签: pythonmysqlpandas

解决方案


首先要注意的是,我也受到了同样的“怪癖”的影响,那就是.dt.seconds它并不总是能给你想要的答案。更好的选择是.dt.total_seconds()

接下来进行分组,

df.groupby([‘date’])[‘duration’].sum() > 30*60 # 30 Minutes

这将返回一个 True/False 数组,然后您可以简单地对这些值求和:

sum(df.groupby([‘date’])[‘duration’].sum() > 30*60)


推荐阅读