python - pandas 中按组划分的独特值的一年滚动计数

标签 python pandas group-by

所以我有以下数据框:

Period      group     ID    
20130101     A        10
20130101     A        20
20130301     A        20
20140101     A        20
20140301     A        30
20140401     A        40

20130101     B        11
20130201     B        21
20130401     B        31
20140401     B        41
20140501     B        51

我需要计算去年按group有多少个不同的ID。所以我想要的输出如下所示:

Period      group     num_ids_last_year
20130101     A            2 # ID 10 and 20 in the last year
20130301     A            2 
20140101     A            2 
20140301     A            2 # ID 30 enters, ID 10 leaves
20140401     A            3 # ID 40 enters

20130101     B            1
20130201     B            2
20130401     B            3
20140401     B            2 # ID 11 and 21 leave 
20140501     B            2 # ID 31 leaves, ID 51 enters

期间采用日期时间格式。我尝试了很多事情:

df.groupby(['group','Period'])['ID'].nunique() # Get number of IDs by group in a given period.
df.groupby(['group'])['ID'].nunique() # Get total number of IDs by group.

df.set_index('Period').groupby('group')['ID'].rolling(window=1, freq='Y').nunique()

但最后一个是不可能的。有什么简单的方法可以做到这一点吗?我想可能是 cumcount() 和 pd.DateOffset 的某种组合,或者可能是 ge(df.Period - dt.timedelta(365)) code>,但我找不到答案。

谢谢。

编辑:添加了这样一个事实:我可以在给定的Period中找到多个ID

最佳答案

查看您的数据结构,我猜您有许多重复项,因此请先删除它们。 drop_duplicates往往很快

我假设df['Period']列的 dtype 为 datetime64[ns]

df = df.drop_duplicates()
results = dict()
for start in df['Period'].drop_duplicates():
    end = start.date() - relativedelta(years=1)
    screen = (df.Period <= start) & (df.Period >= end)  # screen for 1 year of data
    singles = df.loc[screen, ['group', 'ID']].drop_duplicates()  # screen for same year ID by groups
    x = singles.groupby('group').count()
    results[start] = x
results = pd.concat(results, 0)


results
                  ID
           group    
2013-01-01 A       2
           B       1
2013-02-01 A       2
           B       2
2013-03-01 A       2
           B       2
2013-04-01 A       2
           B       3
2014-01-01 A       2
           B       3
2014-03-01 A       2
           B       1
2014-04-01 A       3
           B       2
2014-05-01 A       3
           B       2

这样更快吗?

附:如果df['Period']不是日期时间:

df['Period'] = pd.to_datetime(df['Period'],format='%Y%m%d', errors='ignore')

关于python - pandas 中按组划分的独特值的一年滚动计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59687779/

相关文章:

mysql - 尝试乘以列,但在 mySQL 中分组时无法添加不同的列

python - 使用 ctypes 时 undefined symbol

python - Keras 2.0.8 仅在 Python 3.x 中执行 1 epoch,在 2.x 中执行 10 epoch

python - numpy:二维矩阵的行乘积

python - 如何在 Python for 循环中使用多个变量?

python - 如何根据特定的键值对比较两个 pandas 系列?

python - 如何在pandas中划分一组中的两个连续行

group-by - dask dataframe groupby 导致一个分区内存问题

mysql - 我使用 CASE 语句的查询有什么问题

Pandas 按一个热编码列分组