如何根据 pandas 的组获取变量的滞后值?
How to get the lagged values of a variable based on groups with pandas?
我想找到按连续值对数据进行分组的最有效方法,并创建一个新变量,在每组中给出前一组的值(第一组除外,其中的值应该相同).
我现在可能不是很清楚,所以这是一个玩具示例:
import pandas as pd
var = [1,1,1,2,2,3,1,1,2,4,4,4]
toy_df = pd.DataFrame(var, columns = ['var'])
我想要的输出如下:
desired_output = pd.DataFrame(
{'var': var,
'lagged_var':[1,1,1,1,1,2,3,3,1,2,2,2]}
)
var lagged_var
0 1 1
1 1 1
2 1 1
3 2 1
4 2 1
5 3 2
6 1 3
7 1 3
8 2 1
9 4 2
10 4 2
11 4 2
到目前为止,我想出了以下函数来解决问题:
def make_lag(var):
groups = ( var.shift() != var ).cumsum()
var_shifted = pd.Series([0]*len(var))
for n_gp in groups.unique():
if n_gp == 1:
var_shifted[groups == n_gp] = var[groups == n_gp]
else:
var_shifted[groups == n_gp] = var[groups == n_gp - 1].iloc[0]
return ( var_shifted )
和
toy_df['lagged_values'] = toy_df.apply(lambda x: make_lag(x))
给出了想要的输出。但是,我怀疑它效率很低,因为它涉及遍历所有行。有人知道产生相同输出的矢量化方法吗?(我必须对数百个很长的时间序列重复这个任务,这真的很节省时间!)
非常感谢!
对下一个值使用Series.shift
,如果匹配原始值则替换,然后通过向前和向后填充缺失值来重复值:
s = toy_df['var'].shift()
toy_df['new'] = s.mask(toy_df['var'].eq(s)).ffill().bfill()
print (toy_df)
var new
0 1 1.0
1 1 1.0
2 1 1.0
3 2 1.0
4 2 1.0
5 3 2.0
6 1 3.0
7 1 3.0
8 2 1.0
9 4 2.0
10 4 2.0
11 4 2.0
如果要将值转换为整数:
s = toy_df['var'].shift()
toy_df['new'] = s.mask(toy_df['var'].eq(s)).ffill().bfill().astype(int)
print (toy_df)
var new
0 1 1
1 1 1
2 1 1
3 2 1
4 2 1
5 3 2
6 1 3
7 1 3
8 2 1
9 4 2
10 4 2
11 4 2
我想找到按连续值对数据进行分组的最有效方法,并创建一个新变量,在每组中给出前一组的值(第一组除外,其中的值应该相同).
我现在可能不是很清楚,所以这是一个玩具示例:
import pandas as pd
var = [1,1,1,2,2,3,1,1,2,4,4,4]
toy_df = pd.DataFrame(var, columns = ['var'])
我想要的输出如下:
desired_output = pd.DataFrame(
{'var': var,
'lagged_var':[1,1,1,1,1,2,3,3,1,2,2,2]}
)
var lagged_var
0 1 1
1 1 1
2 1 1
3 2 1
4 2 1
5 3 2
6 1 3
7 1 3
8 2 1
9 4 2
10 4 2
11 4 2
到目前为止,我想出了以下函数来解决问题:
def make_lag(var):
groups = ( var.shift() != var ).cumsum()
var_shifted = pd.Series([0]*len(var))
for n_gp in groups.unique():
if n_gp == 1:
var_shifted[groups == n_gp] = var[groups == n_gp]
else:
var_shifted[groups == n_gp] = var[groups == n_gp - 1].iloc[0]
return ( var_shifted )
和
toy_df['lagged_values'] = toy_df.apply(lambda x: make_lag(x))
给出了想要的输出。但是,我怀疑它效率很低,因为它涉及遍历所有行。有人知道产生相同输出的矢量化方法吗?(我必须对数百个很长的时间序列重复这个任务,这真的很节省时间!)
非常感谢!
对下一个值使用Series.shift
,如果匹配原始值则替换,然后通过向前和向后填充缺失值来重复值:
s = toy_df['var'].shift()
toy_df['new'] = s.mask(toy_df['var'].eq(s)).ffill().bfill()
print (toy_df)
var new
0 1 1.0
1 1 1.0
2 1 1.0
3 2 1.0
4 2 1.0
5 3 2.0
6 1 3.0
7 1 3.0
8 2 1.0
9 4 2.0
10 4 2.0
11 4 2.0
如果要将值转换为整数:
s = toy_df['var'].shift()
toy_df['new'] = s.mask(toy_df['var'].eq(s)).ffill().bfill().astype(int)
print (toy_df)
var new
0 1 1
1 1 1
2 1 1
3 2 1
4 2 1
5 3 2
6 1 3
7 1 3
8 2 1
9 4 2
10 4 2
11 4 2