我编写了一个数据框来说明我的问题。说,我有三个病人:'a','b','c'。我们在三个不同的时间点(t1,t2,t3)得到了这些患者的结果。我需要的是创建另一个列'Fold',这是从t1开始的倍数变化。由于患者'c'在t1没有任何结果,因此其对t1的倍数变化应为nan
。
以下是代码:
df = pd.DataFrame ({ \
'time': np.repeat(['t1','t2','t3'], [2,3,3]),
'id': ['a', 'b', 'a', 'b', 'c', 'a', 'b', 'c'],
'result':np.random.randint(10,20,size=8) })
# create indicator column has_t1: if a patient has t1: 1 if not: 0
df['is_t1'] = np.where(df['time']=='t1', 1, 0)
df['has_t1'] = df.groupby('id')['is_t1'].transform(sum)
# create fold change column
df['fold'] =df.sort_values(['id', 'time']).groupby('id').apply(lambda x: x['result']/x['result'].iloc[0] if x['has_t1'].iloc[0]==1 else np.nan)
我收到了错误:
AttributeError: 'float' object has no attribute 'index'
我想要的输出类似于:
Fold
id time
a t1 1.000000
t2 1.545455
t3 1.000000
b t1 1.000000
t2 1.062500
t3 0.937500
c
t2 NaN
t3 NaN
有谁知道我做错了什么?感谢您的帮助。
答案 0 :(得分:2)
这是一种不涉及指标列的替代方法。首先,unstack
然后重新stack
而不删除NaN:
df = df.set_index(['id', 'time']).unstack().stack(dropna=False)
df
result
id time
a t1 12.0
t2 18.0
t3 13.0
b t1 13.0
t2 11.0
t3 13.0
c t1 NaN
t2 13.0
t3 17.0
接下来,拨打groupby
+ transform
+ head
并将df.result
除以此输出:
df['result'] /= df.groupby(level=0).result.transform('head', 1)
df
result
id time
a t1 1.000000
t2 1.545455
t3 1.000000
b t1 1.000000
t2 1.062500
t3 0.937500
c t1 NaN
t2 NaN
t3 NaN
答案 1 :(得分:1)
s=df.set_index(['id','time']).reindex(pd.MultiIndex.from_product([set(df.id.tolist()),set(df.time.tolist())]))
s=s.sort_index()
s.result.div(s.groupby(level=0).result.nth(0),level=0)
Out[256]:
a t1 1.000000
t2 1.900000
t3 1.800000
b t1 1.000000
t2 0.736842
t3 0.578947
c t1 NaN
t2 NaN
t3 NaN
Name: result, dtype: float64
答案 2 :(得分:0)
使用groupby,apply和stack的另一种方法。
def fold(x):
df_tmp = x.set_index('time')
df_tmp = df_tmp.reindex(df_tmp.index.union(['t1']))
return df_tmp.result.div(df_tmp.loc['t1','result'])
df.groupby('id').apply(fold).stack(dropna=False)
Out[229]:
id result
a t1 1.000000
t2 0.923077
t3 0.923077
b t1 1.000000
t2 1.300000
t3 1.400000
c t1 NaN
t2 NaN
t3 NaN