在引用和循环通过另一个df时在Pandas中使用Apply函数?

时间:2018-11-27 18:15:50

标签: python-3.x pandas loops numpy

我有一个称为df_drug_ref的药品参考资料(如下)。一共有三种药物(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代码与药物参考和药物参考相匹配,我想为相应的药物分配“ 1”(迭代循环以检查A,B或C并分配给相应的列) 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作为参考。

2 个答案:

答案 0 :(得分: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”中的值在{Dell_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_indexreset_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())

也许更快。

答案 1 :(得分:1)

这是使用函数和迭代功能的可行解决方案:

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)