Python。通过多列搜索并识别包含列表中任何元素的行。

问题描述 投票:0回答:1

我最近发了一个关于如何使用R的子集的问题。在R中根据向量中指定的列表子集数据框(使用 "start with "表达式或等价物)。

用户@Ric S非常友好地提供了这个问题的R答案。R的解决方案是。

library(dplyr)
df %>% 
  filter_at(vars(-ID), any_vars(grepl(paste(medications, collapse = "|"), .)))

然而,我的印象是Python可能更省时。总结一下,我试图在一个超过100万行的数据集中识别任何参与者处方的他汀类药物,并在此基础上进行子集。我有一个列表,其中包括这些药物的所有代码(我只是为了演示而编造了一些),接下来我想通过数据框架进行搜索,并将其子集到任何有药物代码 "以" 任何 的元素。在这个例子中,循环似乎是多余的,但我将为一些药物类别运行这个代码。

示例数据集,称为 meds_df:

     ID readcode_1 readcode_2 generic_name
1  1001       bxd1 1146785342  Simvastatin
2  1002       <NA>       <NA>         <NA>
3  1003       <NA>       <NA>  Pravastatin
4  1004       <NA>       <NA>         <NA>
5  1005       bxd4   45432344         <NA>
6  1006       <NA>       <NA>         <NA>
7  1007       <NA>       <NA>         <NA>
8  1008       <NA>       <NA>         <NA>
9  1009       <NA>       <NA>         <NA>
10 1010       bxde       <NA>         <NA>
11 1011       <NA>       <NA>         <NA>

与预期的输出是。

     ID readcode_1 readcode_2 generic_name
1  1001       bxd1 1146785342  Simvastatin
3  1003       <NA>       <NA>  Pravastatin
5  1005       bxd4   45432344         <NA>
10 1010       bxde       <NA>         <NA>

根据其他stackoverflow的问题,我的代码到目前为止,我还需要在这里嵌入any()或类似的代码。

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]
variable_list = ['statins']
for m in variable_list:
    print('extracting individuals prescribed %s' %m)
test = meds_df.loc[meds_df['readcode_1', 'readcode_2','generic_name'].str.startswith(list_to_extract, na=False)]
    print(test)

Error recieved:

KeyError: ('readcode_1', 'readcode_2','generic_name')

任何帮助都将是非常感激的!

python pandas dataframe subset
1个回答
2
投票

首先,正确的语法是 meds_df[['readcode_1', 'readcode_2','generic_name']] (list 的列名)。) 这就是为什么你得到一个 KeyError.

回答你的问题,这里有一个方法可以实现。

# Updated to use tuple per David's suggestion
idx = pd.concat((med_df[col].astype(str).str.startswith(tuple(list_to_extract)) for col in ['readcode_1', 'readcode_2','generic_name']), axis=1).any(axis=1)

med_df.loc[idx]

Result:

      ID readcode_1    readcode_2 generic_name
1   1001       bxd1  1.146785e+09  Simvastatin
3   1003        NaN           NaN  Pravastatin
5   1005       bxd4  4.543234e+07          NaN
10  1010       bxde           NaN          NaN

2
投票

你可以用apply的方法来完成这个任务

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]

bool_df = df[['readcode_1', 'readcode_2','generic_name']].apply(lambda x: x.str.startswith(tuple(list_to_extract), na=False), axis=1)

df.loc[bool_df[bool_df.any(axis=1)].index]

输出:

    ID  readcode_1  readcode_2  generic_name
1   1001    bxd1    1.146785e+09    Simvastatin
3   1003    NaN     NaN             Pravastatin
5   1005    bxd4    4.543234e+07    NaN
10  1010    bxde    NaN             NaN

感谢r. ook发现了一个小错误。


1
投票

另一种解决方案,在重新创建数据框架之前,字符串处理发生在vanilla python中。

list_to_extract = ["bxd", "Simvastatin", "1146785342", "45432344", "Pravastatin"]

cols_to_search = ['readcode_1', 'readcode_2','generic_name']

output = [(ID, *searchbox) 
          for ID, searchbox in zip(df.ID,df.filter(cols_to_search).to_numpy())
          if any([str(box).startswith(tuple(list_to_extract)) for box in searchbox])]

pd.DataFrame(output, columns = df.columns)


     ID readcode_1  readcode_2  generic_name
0   1001    bxd1     1.146785e+09   Simvastatin
1   1003    NaN      NaN            Pravastatin
2   1005    bxd4     4.543234e+07   NaN
3   1010    bxde     NaN            NaN
© www.soinside.com 2019 - 2024. All rights reserved.