簡體   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