【问题标题】:Using apply function in Pandas while referencing and looping through another df?在引用和循环另一个df时在Pandas中使用apply函数?
【发布时间】:2019-04-29 13:18:11
【问题描述】:

我有一个名为 df_drug_ref 的 df 药物参考(如下)。共有三种药物(A、B 和 C)。相应的 ATC 在第二列中列出。但是,如果患者在Drug_BIN_Id_Exclusion 列表中具有 DIN,则她/他将不会被视为使用该药物(即,药物 A 为 011235)。

Drug        Drug_ATC_Id         Drug_DIN_Id_Exclusion
A           N123                [011235]
B           B5234               [65413, 654351]
C           N32456              []

以下是另一个名为df_row的df。这将捕获每个人分配的所有药物。每个人都有自己的People_Id

People_Id   Drug_ATC            Drug_DIN                A           B           C
1001        N123                                        
1001        N123                011235                  
1001        N32456              011232                  
1001        N111                                        
1002        B5234               65413                       
1002        B5234               654090                  
1002        N123                011235                  

如果在该行中,ATC 代码与药物参考匹配并且DIN 不包含在排除列表中。结果应该是:

People_Id   Drug_ATC            Drug_DIN                A           B           C
1001        N123                                        1           0           0
1001        N123                011235                  0           0           0
1001        N32456              011232                  0           0           1
1001        N111                                        0           0           0
1002        B5234               65413                   0           0           0       
1002        B5234               654090                  0           1           0
1002        N123                011235                  0           0           0

我了解如何在同一个 df 本身中使用 apply 函数,但我不知道如何也使用外部 df 作为参考。

【问题讨论】:

    标签: python-3.x pandas loops numpy


    【解决方案1】:

    首先,您可以使用apply(pd.Series)join 将列表拆分为几列df_drug_ref

    print (df_drug_ref.join(df_drug_ref['Drug_DIN_Id_Exclusion'].apply(pd.Series)))
      Drug Drug_ATC_Id Drug_DIN_Id_Exclusion       0       1
    0    A        N123              [011235]  011235     NaN
    1    B       B5234       [65413, 654351]   65413  654351
    2    C      N32456                    []     NaN     NaN
    

    然后你可以merge在列'Drug_ATC'上面加入数据框到People_Id,在对列进行一些清理之后:

    df_merge = People_Id.merge(df_drug_ref[['Drug', 'Drug_ATC_Id']]
                                            .join(df_drug_ref['Drug_DIN_Id_Exclusion']
                                                             .apply(pd.Series)
                                                             .add_prefix('Drug_DIN_'))
                                          .rename(columns={'Drug_ATC_Id':'Drug_ATC'}),
                               how='left')
    

    获取df_merge:

       People_Id Drug_ATC Drug_DIN Drug Drug_DIN_0 Drug_DIN_1
    0       1001     N123             A     011235        NaN
    1       1001     N123   011235    A     011235        NaN
    2       1001   N32456   011235    C        NaN        NaN
    3       1001     N111           NaN        NaN        NaN
    4       1002    B5234    65413    B      65413     654351
    5       1002    B5234   654090    B      65413     654351
    6       1002     N123   011235    A     011235        NaN
    

    现在您可以用 NaN 替换“Drug”列,其中“Drug_DIN”中的值位于“Drug_DIN_i”列之一中,np.any

    mask = np.any(df_merge.filter(like='Drug_DIN').iloc[:,:1].values == 
                  df_merge.filter(like='Drug_DIN').iloc[:,1:].values, axis=1)
    df_merge.loc[mask,'Drug'] = np.nan
    

    最后,要创建列 A、B、C ...,您可以使用 pd.get_dummiesset_index,然后使用 reset_index

    new_People_Id = pd.get_dummies(df_merge.set_index(['People_Id','Drug_ATC','Drug_DIN'])['Drug']).reset_index()
    print (new_People_Id)
       People_Id Drug_ATC Drug_DIN  A  B  C
    0       1001     N123           1  0  0
    1       1001     N123   011235  0  0  0
    2       1001   N32456   011235  0  0  1
    3       1001     N111           0  0  0
    4       1002    B5234    65413  0  0  0
    5       1002    B5234   654090  0  1  0
    6       1002     N123   011235  0  0  0
    

    注意这里也可以使用join 如:

    new_People_Id = df_merge[['People_Id','Drug_ATC','Drug_DIN']].join(df_merge['Drug'].str.get_dummies())
    

    也许更快。

    【讨论】:

      【解决方案2】:

      这是一个使用函数和 iterrows 的可行解决方案:

      def check_rx_condition(row):
          for index, col in df_drug_ref.iterrows():
              if ((col['Drug_ATC_Id'] in row['Drug_ATC'])&
                  (row['DRUG_DIN'] not in col['Drug_DIN_Id_Exclusion'])):
                  row[col['Drug']] = 1
              else:
                  row[col['Drug']] = 0
          return row
      
      df_row = df_row.apply(check_rx_condition, axis=1)
      

      【讨论】:

        猜你喜欢
        • 2019-11-23
        • 2016-05-05
        • 2022-01-20
        • 2017-02-24
        • 1970-01-01
        • 1970-01-01
        • 2020-12-07
        • 2020-09-10
        • 1970-01-01
        相关资源
        最近更新 更多