【问题标题】:Python: Searching through multiple columns and identifying rows that contain any of the elements in a listPython:搜索多个列并识别包含列表中任何元素的行
【发布时间】:2020-06-04 18:48:47
【问题描述】:

我最近发布了一个关于如何使用 R 进行子集化的问题:Subset dataframe in R based on a list specified in a vector (using a 'starts with' expression or equivalent)

用户@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)

收到错误:

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

任何帮助将不胜感激!

【问题讨论】:

  • 尝试在列名周围添加一组额外的括号以进行索引,如下所示:meds_df[['readcode_1', 'readcode_2','generic_name']].str.startswith( ... )
  • @bug_spray 不幸的是,当您按列列表进行切片时,它将返回一个 DataFrame 对象,该对象没有可用的str 方法(直到您到达系列级别)。
  • @r.ook 你是对的。我不知何故忽略了这一点

标签: python pandas dataframe subset


【解决方案1】:

首先,正确的语法是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]

结果:

      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

【讨论】:

  • 不错的答案!如果你转换成元组list_to_extract你实际上不需要迭代它,但你可以直接将它传递给startswith
【解决方案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 发现一个小错误

【讨论】:

  • @sammywemmy 你说得对,我把它从答案中删除了,谢谢!
【解决方案3】:

另一种解决方案,其中在重新创建数据帧之前在 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

【讨论】:

    猜你喜欢
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    • 2016-06-27
    • 2019-07-12
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多