【问题标题】:Replacing with different values based on numerical or alphabetical根据数字或字母替换不同的值
【发布时间】:2021-10-27 09:34:18
【问题描述】:

以下是相关 df 的简化版本:

df = pd.DataFrame({'col':['1_2_abc_def','34_567','8_910_ghi','11_12jkl']})

df

       col
0   1_2_abc_def
1   34_567
2   8_910_ghi
3   11_12jk
   

col 包含字符串值。当_分隔数字时,我希望将其替换为.,当_分隔字母或数字与字母时,我希望将其替换为空格。

预期的df:

        col
0   1.2 abc def
1   34.567
2   8.910 ghi
3   11.12jkl

请注意,所有其他未提及的情况都需要将“_”替换为空格。

我们将不胜感激。

【问题讨论】:

  • 您能在我的答案下方查看 HenryEcker 的评论吗?最后,应该替换所有“_”还是只替换您的 2 个特定情况?

标签: python regex pandas


【解决方案1】:

替代方案:使用replace 而不是str.replace,如下所示:

>>> df.replace({'col': {r'(\d)_(\d)': r'\1.\2', r'_': ' '}}, regex=True)

           col
0  1.2 abc def
1       34.567
2    8.910 ghi
3     11.12jkl

使用此方法,您可以使用嵌套字典来替换值。由于dict 现在是有序的(或使用defaultdict),您可以将其用作对字符串的有序操作序列。首先,所有出现的 'digit_digit' 都将替换为 'digit.digit' 然后所有剩余的 '_' 将替换为 ' '。

【讨论】:

  • 还假设所有 '_' 都必须被替换(对于 OP 的示例来说是这样)。
  • 也许r'([^\W_])_([^\W_])': r'\1 \2' ?
  • @HenryEcker。我理解你的正则表达式,但我不知道为什么它应该替换_': ' '。我错过了一个用例吗?有时间可以解释一下吗?
  • “当 _ 分隔字母或数字和字母时,我希望将其替换为空格”这意味着不应替换 ._. 或 ?_! 之类的内容,除非我误解了 OP。
  • @HenryEcker。谢谢!。我要求 OP 检查您的评论。
【解决方案2】:

先替换<digit>_<digit>,然后替换<letter_or_digit>_<letter_or_digit>。

df['col'].str.replace('(\d)_(\d)', r'\1.\2').str.replace('([aA-zZ]|\d)_([aA-zZ]|\d)', r'\1 \2')

【讨论】:

  • 恕我直言,这是不必要的冗长,没有必要捕捉和恢复。
  • @mozway 这种情况取决于您对 df 中可能包含的字符串所做的假设。对于 OP 的具体示例,您是正确的。
【解决方案3】:

您可以使用带有前瞻功能的正则表达式:

df['col'].replace({'_(?=\D)': ' ', '_(?=\d)': '.'}, regex=True)

说明:如果非数字(\D)后跟“_”,则替换为空格,否则如果数字(\d)后跟_,则替换为.。

或

df['col'] = df['col'].str.replace('_(?=\d)', '.').str.replace('_', ' ')

或

df['col'].str.replace('_(?=\D)', ' ').str.replace('_', '.')

pandas > 1.1,需要指定regex=True选项以避免警告:

df['col'].str.replace('_(?=\D)', ' ', regex=True).str.replace('_', '.', regex=True)

【讨论】:

  • 更新您的 Pandas 版本。对于最新版本,如果您不添加 regex=True,str.replace 会引发 FutureWarning:FutureWarning: The default value of regex will change from True to False in a future version.
  • 是的,没错,谢谢@Corralien,我对此添加了评论(虽然不是每个人都在使用最新版本)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-23
  • 2021-08-15
相关资源
最近更新 更多