【问题标题】:Filter for rows if any value in a list of substrings is contained in any column in a dataframe如果子字符串列表中的任何值包含在数据框中的任何列中,则过滤行
【发布时间】:2021-02-11 11:42:52
【问题描述】:

假设我有一个数据框 df 为:

df = pd.DataFrame({'Index': [1, 2, 3, 4, 5],
                   'Name': ['A', 'B', 100, 'C', 'D'],
                   'col1': [np.nan, 'bbby', 'cccy', 'dddy', 'EEEEE'],
                   'col2': ['water', np.nan, 'WATER', 'soil', 'cold air'],
                   'col3': ['watermelone', 'hot AIR', 'air conditioner', 'drink', 50000],
                  'Results': [1000, 2000, 3000, 4000, 5000]})


Out

Index  Name  col1     col2         col3           Results
    1  A     NaN    water       watermelone        1000
    2  B     bbbY    NaN         hot AIR           2000
    3  100   cccY    water       air conditioner   3000
    4  C     dddf    soil        drink             4000
    5  D     EEEEE   cold air    50000             5000

我有一个清单:matches = ['wat','air']

如何选择col1col2col3matches 中包含i 的所有行。

预期输出:

Index  Name  col1     col2         col3           Results
    1  A     NaN     water       watermelone       1000
    2  B     bbbY    NaN         hot AIR           2000
    3  100   cccY    water       air conditioner   3000

    5  D     EEEEE   cold air    50000              5000

【问题讨论】:

    标签: python pandas dataframe substring


    【解决方案1】:

    您可以使用.T 转置数据帧并使用str.contains 按列检查值然后转回(如果用| 分隔,str.contains 也可以传递多个值,这就是为什么我将列表更改为带有matches = '|'.join(matches) 的字符串。

    转置数据框的好处是您可以使用按列的 pandas 方法,而不是循环遍历行或长 lambda x: 列表理解。 This technique should have good performancelambda xaxis=1 相比答案:

    # df = df.set_index('Index')
    matches = ['wat','air']
    matches = '|'.join(matches)
    df = df.reset_index(drop=True).T.fillna('')
    df = df.T[[df[col].str.lower().str.contains(matches).values.any() for col in df.columns]]
    df
    Out[1]: 
      Name   col1      col2             col3
    0    A            water      watermelone
    1    B   bbbY                    hot AIR
    2    B   cccY     water  air conditioner
    4    D  EEEEE  cold air              eat
    

    【讨论】:

    • @Joe 你能把df = df.T 改成df = df.T.fillna('') - 查看我更新的答案。
    • @Joe 我看到你更新了你的问题。我添加了.fillna('') 来处理空格并将case=False 传递给str.contains() 以忽略大写与小写。
    • 嗨@David Erickson,非常感谢。我运行另一个大数据集,给了我"None of [Float64Index([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,\n ...\n nan, nan, nan, nan, nan, nan, nan, nan, nan, nan],\n dtype='float64', length=4237)] are in the [columns]"
    • @Joe 看起来您的索引上有一个浮点数和 nans。请参阅我的更新答案。我已经用.reset_index(drop=True)重置了索引
    • 嗨@David Erickson,似乎是因为我的数据库中有浮点数,无法匹配字符串。我添加了df = df.applymap(str)。现在可以。非常感谢!!!
    【解决方案2】:

    也试试这个:

    df = df[df['col1'].str.contains('|'.join(matches))|df['col2'].str.contains('|'.join(matches))|df['col3'].str.contains('|'.join(matches))]
    

    打印:

      Name   col1      col2             col3
    1    A   aadY     water      watermelone
    2    B   bbbY       air          hot AIR
    3    B   cccY     water  air conditioner
    5    D  EEEEE  cold air              eat
    

    【讨论】:

      猜你喜欢
      • 2018-01-21
      • 2019-10-08
      • 1970-01-01
      • 2020-04-28
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 2020-03-03
      • 1970-01-01
      相关资源
      最近更新 更多