计算 pandas 中分组元素之间的差异
Calculate difference between grouped elements in pandas
我有一个如下所示的数据框:
df = pd.DataFrame({'patient_id': ['p1', 'p2', 'p3', 'p1', 'p2', 'p3'],
'treatment_time': ['pre', 'pre', 'pre', 'post', 'post', 'post'],
'val1': [1, 4, 9, 2, 6, 10],
'val2': [3, 5, 11, 1, 4, 9],
'val3': [2, 4, 6, 3, 5, 7],
})
print(df)
patient_id treatment_time val1 val2 val3
0 p1 pre 1 3 2
1 p2 pre 4 5 4
2 p3 pre 9 11 6
3 p1 post 2 1 3
4 p2 post 6 4 5
5 p3 post 10 9 7
我的目标是按 patient_id
和 treatment_time
对数据进行分组,并计算治疗前和 post-治疗值之间的差异。预期输出应如下所示:
patient_id val1 val2 val3
0 p1 1.0 -2.0 1.0
1 p2 2.0 -1.0 1.0
2 p3 1.0 -2.0 1.0
使用DataFrame.set_index
with subtract in MultiIndex DataFrame
selected by DataFrame.xs
:
df1 = df.set_index(['patient_id','treatment_time'])
print (df1)
val1 val2 val3
patient_id treatment_time
p1 pre 1 3 2
p2 pre 4 5 4
p3 pre 9 11 6
p1 post 2 1 3
p2 post 6 4 5
p3 post 10 9 7
df = df1.xs('post', level=1).sub(df1.xs('pre', level=1)).reset_index()
print (df)
patient_id val1 val2 val3
0 p1 1 -2 1
1 p2 2 -1 1
2 p3 1 -2 1
如果每个 patient_id 总是只有一个 'pre' 和 'post',并且行被排序为总是先有前,后有 post,那么一个简单的技巧就是是:
cols = df.filter(like='val').columns
out = df.groupby('patient_id')[cols].diff().dropna(how='all')
输出:
>>> out
val1 val2 val3
3 1.0 -2.0 1.0
4 2.0 -1.0 1.0
5 1.0 -2.0 1.0
对行进行排序(如果需要)
df = df.sort_values(by='treatment_time', ascending=False)
创建一个 MultiIndex 数据帧,通过 pd.pivot
并从 post
中减去 pre
:
temp = df.pivot('patient_id', 'treatment_time').swaplevel(axis=1)
temp['post'] - temp['pre']
val1 val2 val3
patient_id
p1 1 -2 1
p2 2 -1 1
p3 1 -2 1
我有一个如下所示的数据框:
df = pd.DataFrame({'patient_id': ['p1', 'p2', 'p3', 'p1', 'p2', 'p3'],
'treatment_time': ['pre', 'pre', 'pre', 'post', 'post', 'post'],
'val1': [1, 4, 9, 2, 6, 10],
'val2': [3, 5, 11, 1, 4, 9],
'val3': [2, 4, 6, 3, 5, 7],
})
print(df)
patient_id treatment_time val1 val2 val3
0 p1 pre 1 3 2
1 p2 pre 4 5 4
2 p3 pre 9 11 6
3 p1 post 2 1 3
4 p2 post 6 4 5
5 p3 post 10 9 7
我的目标是按 patient_id
和 treatment_time
对数据进行分组,并计算治疗前和 post-治疗值之间的差异。预期输出应如下所示:
patient_id val1 val2 val3
0 p1 1.0 -2.0 1.0
1 p2 2.0 -1.0 1.0
2 p3 1.0 -2.0 1.0
使用DataFrame.set_index
with subtract in MultiIndex DataFrame
selected by DataFrame.xs
:
df1 = df.set_index(['patient_id','treatment_time'])
print (df1)
val1 val2 val3
patient_id treatment_time
p1 pre 1 3 2
p2 pre 4 5 4
p3 pre 9 11 6
p1 post 2 1 3
p2 post 6 4 5
p3 post 10 9 7
df = df1.xs('post', level=1).sub(df1.xs('pre', level=1)).reset_index()
print (df)
patient_id val1 val2 val3
0 p1 1 -2 1
1 p2 2 -1 1
2 p3 1 -2 1
如果每个 patient_id 总是只有一个 'pre' 和 'post',并且行被排序为总是先有前,后有 post,那么一个简单的技巧就是是:
cols = df.filter(like='val').columns
out = df.groupby('patient_id')[cols].diff().dropna(how='all')
输出:
>>> out
val1 val2 val3
3 1.0 -2.0 1.0
4 2.0 -1.0 1.0
5 1.0 -2.0 1.0
对行进行排序(如果需要)
df = df.sort_values(by='treatment_time', ascending=False)
创建一个 MultiIndex 数据帧,通过 pd.pivot
并从 post
中减去 pre
:
temp = df.pivot('patient_id', 'treatment_time').swaplevel(axis=1)
temp['post'] - temp['pre']
val1 val2 val3
patient_id
p1 1 -2 1
p2 2 -1 1
p3 1 -2 1