我有一个数据框:
c1 Lag Val1
A 3 10
A 1 5
A 2 20
A 2 15
A 1 10
B 1 25
B 2 10
我想创建一个新字段val2,以使val2中的每个值都是val2中的值移动滞后行数。这里最棘手的部分是,移位应该发生在字段c1中定义的组内,这样输出看起来就类似于
c1 Lag Val1 Val2
A 3 10 15
A 1 5 20
A 2 20 10
A 2 15 NaN
A 1 10 NaN
B 1 25 10
B 2 10 NaN
我一直在尝试与
df['Val2'] = df.groupby(['c1'])['Val1'].apply(lambda x:x.shift(df.Lag))
无济于事,并得到“系列的真相值不明确”。错误。感谢任何帮助。谢谢!
答案 0 :(得分:2)
您可以使用self merge
并稍加操作索引即可完成此操作:
# Copy and keep only the columns that are relevant
df2 = df.rename(columns={'Val1': 'Val2'}).drop(columns='Lag').copy()
# Shift the index
df.index = df.index+df.Lag
# Merge, requiring match on shifted index and within group.
df.reset_index().merge(df2.reset_index(), on=['index', 'c1'], how='left').drop(columns='index')
c1 Lag Val1 Val2
0 A 3 10 15.0
1 A 1 5 20.0
2 A 2 20 10.0
3 A 2 15 NaN
4 A 1 10 NaN
5 B 1 25 10.0
6 B 2 10 NaN
答案 1 :(得分:1)
您很可能必须为应用编写自己的函数。这样的事情会起作用,但是可能有比迭代行和重复计算行移位更有效的方法...
def shift_rows(g):
g['Val2'] = np.nan
for i,r in g.iterrows():
g.at[i, 'Val2'] = g['Val1'].shift(-r['Lag'])[i]
return g
output = df.groupby('c1').apply(shift_rows)
print(output)
c1 Lag Val1 Val2
0 A 3 10 15.0
1 A 1 5 20.0
2 A 2 20 10.0
3 A 2 15 NaN
4 A 1 10 NaN
5 B 1 25 10.0
6 B 2 10 NaN
这个想法是遍历groupby对象的每一行,以使用Lag
中的值来计算行移位,然后提取您想要的新值。这将存储到该行的Val2
中,并返回整个组