【问题标题】:How to ignore rows with a mask when using str.contains?使用 str.contains 时如何忽略带掩码的行?
【发布时间】:2020-01-18 00:38:42
【问题描述】:

我有一个必须标准化的商店名称数据框。例如麦当劳 1234 LA -> 麦当劳。您可以在下面看到 PopeyesWallmart 已经标准化:

   id              store  standard
0   1          McDonalds       NaN
1   2               Lidl       NaN
2   3  Lidl New York 123       NaN
3   4                KFC       NaN
4   5      Slidling Shop       NaN
5   6        Lidi Berlin       NaN
6   7         Popeyes NY   Popeyes
7   8  Wallmart LA 90210  Wallmart
8   9               Aldi       NaN
9  10        London Lidl       NaN

我使用str.contains 查找商店名称,并将标准化名称放入standard 列。我在这里标准化 Lidl 商店:

df.loc[df.store.str.contains(r'\blidl\b', case=False), 'standard'] = 'Lidl'

print(df)

   id              store  standard
0   1          McDonalds       NaN
1   2               Lidl      Lidl
2   3  Lidl New York 123      Lidl
3   4                KFC       NaN
4   5      Slidling Shop       NaN
5   6        Lidi Berlin       NaN
6   7         Popeyes NY   Popeyes
7   8  Wallmart LA 90210  Wallmart
8   9               Aldi       NaN
9  10        London Lidl      Lidl

但是这里的问题是它在已经标准化的行上搜索str.contains(Popeyes 和 Wallmart)。

如何仅在 df['standard'] == NaN 所在的行上运行 str.contains 而忽略标准化行?

我尝试了一些非常非常混乱的方法,但它似乎不起作用。我设置了一个掩码,然后在运行str.contains之前使用它:

mask = df['standard'].isna()

df[mask].loc[df[mask].store.str.contains(aldi_regex,na=False), 'standard3'] = 'Aldi'

不起作用。我还尝试了一些更混乱的方法,但没有奏效:

df.loc[mask].loc[df.loc[mask].store.str.contains(aldi_regex,na=False), 'standard3'] = 'Aldi'

如何忽略标准化行?无需诉诸 for 循环。

我的示例数据框:

import pandas as pd
import re

df = pd.DataFrame({'id': pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],dtype='int64',index=pd.RangeIndex(start=0, stop=10, step=1)), 'store': pd.Series(['McDonalds', 'Lidl', 'Lidl New York 123', 'KFC', 'Slidling Shop', 'Lidi Berlin', 'Popeyes NY', 'Wallmart LA 90210', 'Aldi', 'London Lidl'],dtype='object',index=pd.RangeIndex(start=0, stop=10, step=1)), 'standard': pd.Series([pd.np.nan, pd.np.nan, pd.np.nan, pd.np.nan, pd.np.nan, pd.np.nan, 'Popeyes', 'Wallmart', pd.np.nan, pd.np.nan],dtype='object',index=pd.RangeIndex(start=0, stop=10, step=1))}, index=pd.RangeIndex(start=0, stop=10, step=1))

【问题讨论】:

  • 你可以试试df['standard'].mask(df['standard'].isna(),df['store'].str.extract(r'(?i)(\blidl\b)',expand=False)) 吗?
  • 虽然我确信其中一位超级明星可能会给你一个单行,但我认为这很容易通过一个辅助列(甚至是一个列表)来跟踪处理后的名称
  • 您是否尝试过首先过滤 NaN 值? df.loc[df['standard'].notnull() & df.store.str.contains(r'\blidl\b', case=False), 'standard'] = 'Lidl'
  • @hichame.yessou 是的,我认为这可行。我只需要将其更改为df.loc[df['standard'].isnull() 而不是notnull()。 :)
  • @anky_91 至少我学到了一些东西。没听说过.mask()这个函数,我最好查一下。

标签: python pandas


【解决方案1】:

如何忽略标准化行?不诉诸于 循环。

通过过滤检查空值:

df.loc[df['standard'].isnull() & df.store.str.contains(r'\blidl\b', case=False), 'standard'] = 'Lidl'

【讨论】:

    猜你喜欢
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 2015-08-20
    • 1970-01-01
    • 2015-09-22
    • 2020-06-30
    • 1970-01-01
    相关资源
    最近更新 更多