【问题标题】:pandas str.replace - keep current value if regex fails to avoid NaN in converting string to numberspandas str.replace - 如果正则表达式无法避免 NaN 将字符串转换为数字,则保留当前值
【发布时间】:2020-02-19 00:33:40
【问题描述】:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.replace.html

我有一列格式化为字符串的值,其中一些包含逗号,例如:

0     20,7
1       22
2       21
3       20
4     24,4
5     23,8
6     23,6
7     21,6
8     24,3
9     23,3
10    24,2

....

17053      16
17054      16
17055      15
17056      15
17057      19
17058      17
17059      18
17060      19
17061      20
17062      21
17063      20

我想将它们转换为浮点数。

现在,我不能直接应用 astype 或 to_numeric 方法,否则不会解释为“20,7”的字符串。

奇怪的是,如果将.str.replace(',', '.') 应用于不包含该模式的字符串,则正则表达式会失败,并返回 NaN。如果找到模式,我会期待替换,否则返回原样。

我也尝试了.str.replace(',', '.', regex = False),但没有成功。

例子:

对于像“20,7”这样的值,用逗号替换点可以正常工作,然后我可以转换为数字,得到一个浮点数 20.7。

但我也有这些价值观:

test['TMEDIA °C'][-10:]

17054    16
17055    15
17056    15
17057    19
17058    17
17059    18
17060    19
17061    20
17062    21
17063    20

并应用 str.replace 我明白了:

test['TMEDIA °C'][-10:].str.replace(',', '.')

17054   NaN
17055   NaN
17056   NaN
17057   NaN
17058   NaN
17059   NaN
17060   NaN
17061   NaN
17062   NaN
17063   NaN

并且不能将 astype 应用于整个列,而是我想得到这个:

test['TMEDIA °C'][-10:].astype(float)
17054    16.0
17055    15.0
17056    15.0
17057    19.0
17058    17.0
17059    18.0
17060    19.0
17061    20.0
17062    21.0
17063    20.0

这是 str.replace() 的错误,还是如果正则表达式失败,我如何保持当前值?

【问题讨论】:

  • 不,无论如何它都会失败,无法将字符串转换为浮点数。我的问题的解决方案是test['TMEDIA °C'].apply(lambda x : str(x).replace(',','.')).astype(float) ,但我正在等待将其发布为答案,因为我希望更好地了解 pandas 的 srt.replace 方法是否也可以让结果找到。
  • 1) str.replace(',', '.') 在我的系统上运行良好(pandas 0.25)。 2)你也许可以用pd.read_csv(thousands=',')解决你的问题。
  • @QuangHoang “工作正常”是指不包含逗号的值被保留(你没有得到 NaN)?
  • 这正是我的意思。请参阅live code

标签: python regex pandas replace


【解决方案1】:

您很可能有一个包含混合数据类型的列,如下所示:

fails = pd.DataFrame([['1,2'], [3]], columns=['a'])
print(fails['a'].str.replace(',', '.'))  # results in NaN

专栏是如何结束的,是另一个问题。如果你有:

works = pd.DataFrame([['1,2'], ['3']], columns=['a'])

然后就可以了。

例如,如果您连接两个数据帧,则可能会出现混合数据类型:

df1 = pd.DataFrame([['1,2']], columns=['a'])
df2 = pd.DataFrame([[3]], columns=['a'])
fails = pd.concat([df1, df2])

如果df2 是由read_csv 生成的,并且它没有"," 值,那么它会自动解析为数字而不是字符串。

您可以通过在包含逗号值的数据帧上使用.str.replace(此处为df1之前与其他数据帧连接)或确保其他数据框的列(此处为d2['a'])也有dtype=str(例如通过read_csv(..., dtype=str))。

【讨论】:

  • 确实我连接了。你是对的,混合数据类型。我迷失了方向,因为我看到所有列的dtypeÒbject,尽管所有值都是相同类型的实例,但它是整数和逗号的混合。谢谢你的解释。
  • @user305883 那么解决此问题的最佳方法是在连接之前使用, 值(此处为df1)清理数据框(即使用.str.replace),或指定@987654338 @ 代表read_csv 代表没有, 的那个(df2),或者在连接之前转换为str(我会说优先级)。如果它解决了您的问题,请考虑接受其中一个答案,以便将问题标记为已解决。
  • 你是对的。关于“请考虑接受其中一个答案,以便将问题标记为已解决”。我发现您的答案很清楚,可以解释如何处理数据清理的良好做法;安迪的上述回答是解释我为什么会见 NaN 的简短有效解决方案。我发现并赞成两者都是有用的,我认为两者都是正确的。我很困惑,根据 StackOverflow 的说法,我应该将提供更广泛理解的答案标记为正确,是对问题的一个更准确的点还是我首先阅读的那个..?我在这里发表评论是因为不想冒犯也不推迟你们任何人
  • @user305883 您应该接受用于解决问题的答案。 Andy's answer 建议您在执行替换之前通过将列转换为 str 来解决问题,而我建议通过在与另一个数据帧连接之前对一个数据帧执行替换来避免此问题,或者确保两个数据帧在连接之前有dtype=str(例如通过read_csv(dtype=str))。无论你最终选择了哪种解决方案,你都应该接受。
  • 无论如何,这是您的问题,因此您可以选择接受什么样的答案来解决您的问题。没有人会因此感到被冒犯,这就是网站的运作方式。大多数情况下,我们是来帮忙的,而不是收集积分 :-) 如果你真的很难决定其中一个答案,你也可以选择以下方法:python -c "import random; print(random.choice(['Andy L.', 'a_guest']))" 让 Python 决定一个 Python 问题是可能尽可能公平;-)
【解决方案2】:

那些在replace 之后的NaN 具有dtype int,所以replace 返回NaN。在调用str.replace之前尝试将整列强制转换为str

test['TMEDIA °C'].astype(str).str.replace(',', '.')

【讨论】:

    【解决方案3】:
    s = pd.Series(['foo', 'fuz', 'some other'])
    idx = s[s.str.contains(r'f', regex=True)].index
    s.loc[idx] = s.loc[idx].str.replace('f', 'F')
    display(s)
    
    0           Foo 
    1           Fuz
    2    some other
    dtype: object
    

    【讨论】:

    • 请不要只发布代码作为答案,而是要说明代码的作用以及它如何解决问题的问题。带有解释的答案通常质量更高,更有可能吸引投票。
    猜你喜欢
    • 2016-07-17
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 2012-01-28
    • 2022-11-18
    • 1970-01-01
    相关资源
    最近更新 更多