如何通过在python中的特定时间范围内计算来创建新列?



我有一个这样的数据帧,

ID   col1            col2   
A    2018/07/01       3     
A    2018/08/01       5   
A    2018/10/01       10      
B    2018/07/01       4        
B    2018/10/01       7         
B    2019/01/01       9       
B    2019/04/01       12       
C    2018/07/01       6        
C    2018/09/01       5  
C    2018/10/01       7   

我尝试创建一个新的列col3,它通过col2计算每个 ID 减去 3 个月后。

结果会像,

ID   col1            col2       col3
A    2018/07/01       3          -7
A    2018/08/01       5          NaN
A    2018/10/01       10         NaN
B    2018/07/01       4          -3
B    2018/10/01       7          -2
B    2019/01/01       9          -3
B    2019/04/01       12         NaN
C    2018/07/01       6          -1
C    2018/09/01       5          NaN
C    2018/10/01       7          NaN

如果 3 个月后每个 ID 没有月份查找,则返回 NaN。

据说这很容易shift(freq='-3M')但不知何故不适用于月份开始。所以我们可以做到:

# month end date
df['col1e'] = df.col1 + pd.DateOffset(months=3) - pd.DateOffset(days=1)
# shift by group
new_df = df.set_index('col1e').col2.shift(freq='-3M').reset_index(name='col3')
# copy the ID values
new_df['ID'] = df['ID'].values
# merge
df = df.merge(new_df, on=['col1e','ID'],how='left')
#final result
df['col3'] = df['col2'] - df['col3']

输出:

ID       col1  col2      col1e  col3
0  A 2018-07-01     3 2018-09-30  -7.0
1  A 2018-08-01     5 2018-10-31   NaN
2  A 2018-10-01    10 2018-12-31   NaN
3  B 2018-07-01     4 2018-09-30  -3.0
4  B 2018-10-01     7 2018-12-31  -2.0
5  B 2019-01-01     9 2019-03-31  -3.0
6  B 2019-04-01    12 2019-06-30   NaN
7  C 2018-07-01     6 2018-09-30  -1.0
8  C 2018-09-01     5 2018-11-30   NaN
9  C 2018-10-01     7 2018-12-31   NaN

按 ID 分组并将日期列设置为索引和重新采样。然后平移 -3。

在:

def func(df):
df = df.set_index(df.col1).resample('MS').asfreq()
df['col3'] = df.col2 - df.col2.shift(-3)
# Clean Up DataFrame        
df = df.reset_index(0, drop=True).reset_index(drop=True).dropna(how='all')
return df
df = pd.read_clipboard()
df.col1 = pd.to_datetime(df.col1)
group = df.groupby('ID', as_index=False)
df = group.apply(func).reset_index(drop=True)

外:

|    | ID | col1       | col2 | col3 |
|----|----|------------|------|------|
| 0  | A  | 2018-07-01 | 3.0  | -7.0 |
| 1  | A  | 2018-08-01 | 5.0  | NaN  |
| 2  | A  | 2018-10-01 | 10.0 | NaN  |
| 3  | B  | 2018-07-01 | 4.0  | -3.0 |
| 4  | B  | 2018-10-01 | 7.0  | -2.0 |
| 5  | B  | 2019-01-01 | 9.0  | -3.0 |
| 6  | B  | 2019-04-01 | 12.0 | NaN  |
| 7  | C  | 2018-07-01 | 6.0  | -1.0 |
| 8  | C  | 2018-09-01 | 5.0  | NaN  |
| 9  | C  | 2018-10-01 | 7.0  | NaN  |

您可以在数据框组中使用"重新索引"(无重新采样和无偏移(:

def get_col2(grp):
return grp.set_index("col1").reindex(grp["date2"],axis="index")["col2"]      
df["col3"]= df.assign(date2=df["col1"]+pd.offsets.MonthBegin(3)).groupby("ID").apply(get_col2).values
df["col3"]= df["col2"]-df["col3"]

输出:

ID       col1  col2  col3
0  A 2018-07-01     3  -7.0
1  A 2018-08-01     5   NaN
2  A 2018-10-01    10   NaN
3  B 2018-07-01     4  -3.0
4  B 2018-10-01     7  -2.0
5  B 2019-01-01     9  -3.0
6  B 2019-04-01    12   NaN
7  C 2018-07-01     6  -1.0
8  C 2018-09-01     5   NaN
9  C 2018-10-01     7   NaN

最新更新