繁体   English   中英

根据熊猫中另一列的值在groupby之后应用lambda函数

[英]apply lambda function after groupby based on values of another column in pandas

我制作了一个数据框来说明我的问题。 说,我有三个病人:“ 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

有人知道我做错了吗? 谢谢您的帮助。

这是一种不涉及指标列的替代方法。 首先,先进行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

嗯,还有另一种方法

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

使用groupby的另一种方法是应用和堆栈。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM