首页 > 解决方案 > Groupby并在熊猫中获得价值抵消一年

问题描述

Category==1我今天的目标是跟踪一年后在给定日期属于的每个 ID 。所以我有一个这样的数据框:

Period      ID    Amount   Category
20130101    1       100       1
20130101    2       150       1
20130101    3       100       1
20130201    1       90        1
20130201    2       140       1
20130201    3       95        1
20130201    5       250       0
   .        .       .
20140101    1       40        1
20140101    2       70        1
20140101    5       160       0
20140201    1       35        1
20140201    2       65        1
20140201    5       150       0

例如,20130201我有 2 个属于Category1 的 ID:1,2,3,但其中只有 2 个出现在201402011,2 中。Amount因此,一年后,我需要仅针对那些 ID 获取 的值,如下所示:

Period      ID    Amount   Category    Amount_t1
20130101    1       100       1           40
20130101    2       150       1           70
20130101    3       100       1           nan
20130201    1       90        1           35
20130201    2       140       1           65
20130201    3       95        1           nan
20130201    5       250       0           nan
   .        .       .
20140101    1       40        1           nan
20140101    2       70        1           nan
20140101    5       160       0           nan
20140201    1       35        1           nan 
20140201    2       65        1           nan
20140201    5       150       0           nan  

所以,如果 ID 明年不出现或不属于Category0,我会得到一个nan. 我的第一种方法是获取每个唯一 ID 的列表,Period然后尝试将其映射到下一年,使用某种组合groupby()isin()如下:

aux = df[df.Category==1].groupby('Period').ID.unique()
aux.index = aux.index + pd.DateOffset(years=1)

但我不知道如何继续前进。我在想某种groupby('ID')可能更有效。如果这很简单shift(),那将很容易,但是我不确定如何按组将值抵消一年。

标签: pythonpandasdatedatetimepandas-groupby

解决方案


在手动滞后一个连接键后,您可以创建具有精确合并的滞后要素。

import pandas as pd

# Datetime so we can do calendar year subtraction
df['Period'] = pd.to_datetime(df.Period, format='%Y%m%d')

# Create one with the lagged features. Here I'll split the steps out.
df2 = df.copy()
df2['Period'] = df2.Period-pd.offsets.DateOffset(years=1)  # 1 year lag
df2 = df2.rename(columns={'Amount': 'Amount_t1'})

# Keep only values you want to merge
df2 = df2[df2.Category.eq(1)]

# Bring lagged features
df.merge(df2, on=['Period', 'ID', 'Category'], how='left')

       Period  ID  Amount  Category  Amount_t1
0  2013-01-01   1     100         1       40.0
1  2013-01-01   2     150         1       70.0
2  2013-01-01   3     100         1        NaN
3  2013-02-01   1      90         1       35.0
4  2013-02-01   2     140         1       65.0
5  2013-02-01   3      95         1        NaN
6  2013-02-01   5     250         0        NaN
7  2014-01-01   1      40         1        NaN
8  2014-01-01   2      70         1        NaN
9  2014-01-01   5     160         0        NaN
10 2014-02-01   1      35         1        NaN
11 2014-02-01   2      65         1        NaN
12 2014-02-01   5     150         0        NaN

推荐阅读