我有一个数据框,其结构类似于下面的示例 df
。这包含 2 个变量,time
和 state
。由于这些是对 identity
的重复观察,因此我想针对 state
的每个级别获得 time
的 1 和 2 之间的差异向量。我用下面的代码做到了这一点,但我觉得这应该比我所做的更容易。
有什么方法可以使这更有效和可靠吗?例如,如果我对 state
有多个级别,我需要在取消堆叠后手动执行它们的差异列(因为我已经做了两次),这似乎有点不灵活。此外,在 axis=1
上运行 sum
感觉非常 hacky。我想知道它是否可以改进,如果能得到一些反馈会很棒。我也不需要总是让我感到困惑的多列级别。
这是我的方式:
import numpy as np
import pandas as pd
ids = [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5]
times = [1,1,2,2,1,1,2,2,1,1,2,2,1,1,2,2,1,1,2,2]
states = ['A', 'B', 'A', 'B'] * 5
np.random.seed(121)
resps = [(i*t) + np.random.normal() for i, t in zip(ids, times)]
DATA = {
'identity': ids,
'time': times,
'state': states,
'resps': resps
}
df = pd.DataFrame(DATA)
df.head()
给我们:
identity time state resps
0 1 1 A 0.787967
1 1 1 B 0.715071
2 1 2 A 1.426102
3 1 2 B 1.559690
4 2 1 A 1.669889
然后以复杂的方式进行差异:
wide = df.set_index(['identity', 'state', 'time']).unstack().reset_index()
A = wide['state']=='A'
B = wide['state']=='B'
wide['diffA'] = wide[A][('resps', 2)] - wide[A][('resps', 1)]
wide['diffB'] = wide[B][('resps', 2)] - wide[B][('resps', 1)]
wide['difference'] = wide[['diffA', 'diffB']].sum(axis=1)
wide = wide.drop(columns=[('diffA', ''), ('diffB', '')])
print(wide)
identity state resps difference
time 1 2
0 1 A 0.787967 1.426102 0.638135
1 1 B 0.715071 1.559690 0.844619
2 2 A 1.669889 5.615373 3.945483
3 2 B 3.183695 4.367062 1.183368
4 3 A 2.985881 7.709641 4.723760
5 3 B 3.629642 4.673013 1.043371
6 4 A 4.401873 9.403826 5.001953
7 4 B 3.808573 6.031231 2.222658
8 5 A 4.209585 10.087744 5.878159
9 5 B 4.267278 9.499714 5.232436
回答1
如果您最感兴趣的只是 difference
列,下面可能会有所帮助:
In [435]: df['difference'] = df.groupby(['identity', 'state'])['resps'].diff()
In [438]: df.dropna()[['identity', 'state', 'difference']]
Out[438]:
identity state difference
2 1 A 0.638135
3 1 B 0.844619
6 2 A 3.945483
7 2 B 1.183368
10 3 A 4.723760
11 3 B 1.043371
14 4 A 5.001953
15 4 B 2.222658
18 5 A 5.878159
19 5 B 5.232436