使用正则表达式过滤 pandas 数据框列,但出现异常

Using regex to filter pandas dataframe columns with an exception

我正在尝试通过使用 pd.filter 和正则表达式字符串来对 python pandas 数据框进行子集化(检索一组行),以便在执行之前识别感兴趣的列基于这些列中的值的子集。

例如,这是我的模拟数据框:

id status status_drug_use drugA drugA_use    drugB  drugB_use
0  1      analgesic       0     None         1      hypertensive
1  0      analgesic       1     analgesic    1      hypertensive
2  0      analgesic       1     hypertensive 0      None
3  1      analgesic       0     None         1      analgesic

我想要包含列 drugA_usedrugB_use 中的值且与 status_drug_use 中的值匹配的所有行。根据示例,这将 return 两行:

id status status_drug_use drugA drugA_use    drugB  drugB_use
1  0      analgesic       1     analgesic    1      hypertensive
3  1      analgesic       0     None         1      analgesic

有一些列名称约定需要遵守:

  1. status_drug_use 一直都在。
  2. 匹配列(drugA_usedrugB_use)始终遵循模板 <ANYTHING>_use

改动 还有第二种情况,在这种情况下,我想在用户定义的字符串(例如 analgesic 和两列 drugA_usedrugB_use 之间执行比较。这与使用 status_drug_use.

的内容不同

这是一种完成您所要求的方法:

df2 = df.assign(all_use=df.apply(
    lambda x: list(x[[col for col in df.columns if col.endswith('_use') and col != 'status_drug_use']]), 
    axis=1)).explode(
    'all_use').query('status_drug_use == all_use').drop_duplicates().drop(columns='all_use')

输入:

  id status status_drug_use drugA     drugA_use drugB     drugB_use
0  0      1       analgesic     0          None     1  hypertensive
1  1      0       analgesic     1     analgesic     1  hypertensive
2  2      0       analgesic     1  hypertensive     0          None
3  3      1       analgesic     0          None     1     analgesic

输出:

  id status status_drug_use drugA  drugA_use drugB     drugB_use
1  1      0       analgesic     1  analgesic     1  hypertensive
3  3      1       analgesic     0       None     1     analgesic

解释:

  • 找到以_use结尾的所有列的子集(不包括status_drug_use
  • 添加一个名为 all_use 的列,其给定行的值是以 _use
  • 结尾的列中的值的列表
  • 使用 explode() 添加行,这样对于每个原始行,现在有多个行,原始行 all_use 中的每个值对应一个
  • 使用 query() 到 select 仅 status_drug_useall_use
  • 中的值匹配的行
  • 使用 drop_duplicates 消除行,以防原始数据框中的任何行有多个匹配项(例如,如果 drugA_usedrugB_use 都包含“镇痛药”等做了 status_drug_use)
  • 删除列 all_use,因为我们不再需要它。

更新:在评论中解决 OP 的问题:'Rather than using the values in column status_drug_use, how do I achieve the same output but by using a single user defined string e.g., "analgesic"?'

您可以通过将用户定义的查询字符串(称为 user_defined_str)作为变量并通过将列名 status_drug_use 替换为带有 @ 前缀的变量名称:@user_defined_str(有关详细信息,请参阅 query() 文档 here)。

user_defined_str = 'analgesic'
df3 = df.assign(all_use=df.apply(
    lambda x: list(x[[col for col in df.columns if col.endswith('_use') and col != 'status_drug_use']]), 
    axis=1)).explode(
    'all_use').query('@user_defined_str == all_use').drop_duplicates().drop(columns='all_use')