【问题标题】:if then else in Regex in DataFrameif then else 在 DataFrame 的 Regex 中
【发布时间】:2021-12-10 05:43:58
【问题描述】:

我正在尝试使包含数千分之一记录的相当混乱的电话簿 xls 合理化。有些字段会与其他字段合并和/或保存到错误的列中,而其他字段则被分成 2 个或更多字段......等等。我正在尝试找到主要错误的路径并通过正则表达式解决这些问题,将正确的记录放入右列。 一个例子: DataFrame 为 df:

id Name SecondName Surname Title Company
01 Marc Gigio ETC ltd
02 Piero (Four Season Restaurant )
03 bubbu(Caterpilar)
04 gaby(ts Inc)
05 Pit(REV inc) REV Inc
06 Pluto
  • 在记录 01 中:无事可做,但请参阅第 5 点如何管理条件异常。

  • 在记录 02 中:合并 Name + SecondName + Surname ,然后从新字符串中提取名称(Piero)放置在 Name 列中,同时从同一字符串中提取方括号的内容并将其放入 Company 列中

    df['Nameall_tmp'] = df[姓名]+' '+df[SecondName]+' '+df[姓氏]+' '+df[公司] df['Name_tmp'] = df[Nameall_tmp].str.extract(r'(.+)(.+') df['Company_tmp'] = df[Nameall_tmp].str.extract(r'.*((.+))')

  • 在记录 03 和 04:几乎是 02

  • 在记录 06 中: df['Nameall_tmp'] = df[Name]+' '+df[SecondName]+' '+df[Surname]+' '+df[Company] df['Name_tmp'] = df['Nameall_tmp'].str.extract(r'(.+)(.+') df['Name_tmp']= np.where(df['Name_tmp'] == 'nan' , df['Name'],df['Name_tmp'] )

在这种情况下 np.where 语句不像 if then else 那样工作,为了检查 df['Name_tmp'] 是否为“nan”,在这种情况下,填写原始 df['Name'] 以消除记录中的“nan”,否则取 df['Name_tmp']。有什么建议吗?

【问题讨论】:

  • 不知道您可以在这里渲染表格。学到东西了,谢谢
  • ;-) 我几乎是一个备用的新的!
  • 您解决了问题还是需要更多帮助?
  • Eliu 的解决方案非常强大,并且可以提供广泛的定制解决方案!有了这个技巧,我可以进一步解决其他情况......只需要在 rex 变量的分配中完善他的正则表达式建议。我需要的是查找和研究有关 Regex 如何在数据框中创建列的文档。这对我来说是完全缺失的。谢谢你,Wiktor

标签: python regex pandas


【解决方案1】:

这里粗略思考:

  1. munge “公司”列,以便:如果它包含合法的公司名称, 添加() 到它。如果没有,请保留原创内容
  2. 将所有列合并为一个联合列
  3. 使用 1 个正则表达式将 sr.str.extract(rex) 再次将单个联合列合并到所需列中

无论如何,经过粗略的思考,我至少将问题简化为微调单个正则表达式:

df = pd.DataFrame(
    columns="   index                 Name    SecondName    Surname         Company ".split(),
    data= [
            [       0,              "Marc",       np.nan,   "Gigio",      "ETC ltd", ],
            [       1,             "Piero",      "(four",  "season",  "restaurant)", ],
            [       2, "bubbu(caterpilar)",       np.nan,    np.nan,         np.nan, ],
            [       3,              np.nan,       np.nan,    np.nan, "gaby(ts inc)", ],
            [       4,      "Pit(REV inc)",       np.nan,    np.nan,      "REV inc", ],
            [       5,             "pluto",       np.nan,    np.nan,         np.nan, ],]).set_index("index", drop=True)

df = df.fillna('')

df['Company'] = df['Company'].apply(lambda x: f'({x})' if ('(' not in x and ')' not in x and x!="") else x)
# df['sum'] = df.sum(axis=1)

df['sum'] = df['Name'] + ' ' + df['SecondName'] + ' ' + df['Surname'] + ' ' + df['Company']
df['sum'] = df['sum'].str.replace(r'\s+', ' ', regex=True) # get rid of extra \s due to above concat

rex = re.compile( # very fragil and hardcoded,
    r"""
    (?P<name0>[a-z]{2,})
    \s?
    (?P<surename0>[a-z]{2,})?
    \s?
    \(? 
    (?P<company0>[a-z\s]{3,})?  
    \)?
    \s?
    """,
    re.X+re.I
)

df['sum'].str.extract(rex)

输出:

+---------+---------+-------------+------------------------+
|   index | name0   | surename0   | company0               |
|---------+---------+-------------+------------------------|
|       0 | Marc    | Gigio       | ETC ltd                |
|       1 | Piero   | nan         | four season restaurant |
|       2 | bubbu   | nan         | caterpilar             |
|       3 | gaby    | nan         | ts inc                 |
|       4 | Pit     | nan         | REV inc                |
|       5 | pluto   | nan         | nan                    |
+---------+---------+-------------+------------------------+

编辑:
较早的答案在我的正则表达式中包含错误(忘记? \(),无法完全处理“冥王星”,现在更正。
这个故事的寓意是,您需要设计的正则表达式将非常专业、脆弱和硬编码。几乎值得考虑使用 df['sum'].apply(myfoo) 方法来更彻底地解析 df['sum']

【讨论】:

  • 谢谢 eliu。由于我是 python 的新手,我需要深入研究你的例程。尤其是rex assignment的最后一部分:它几乎可以工作,但不能清楚地理解(我几乎不知道)rex的构造,最终尝试修改以获得更定制的功能。你帮了我很多,直到现在。谢谢!!
  • 如果您将在未来的工作中处理字符串,正则表达式是一个巨大的推动力。此外,谷歌series.str,其中大部分是基于正则表达式的。使用 linux 的一半涉及正则表达式。如果您喜欢答案,请接受并投票。
  • 我正在阅读关于分组和变量/标签分配 ((?P)) 的正则表达式的帮助部分:令人印象深刻且功能强大的工具!再次感谢让我揭示了编程的新视野!
猜你喜欢
  • 1970-01-01
  • 2015-06-07
  • 2016-11-27
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 2018-08-02
  • 1970-01-01
相关资源
最近更新 更多