【问题标题】:Replace all but last occurrences of a character in a string with pandas用 pandas 替换字符串中除最后一个字符之外的所有字符
【发布时间】:2018-05-28 12:40:13
【问题描述】:

使用 Pandas 删除字符串中除最后一个句点之外的所有句点,如下所示:

s = pd.Series(['1.234.5','123.5','2.345.6','678.9'])
counts = s.str.count('\.')
target = counts==2
target
0     True
1    False
2     True
3    False
dtype: bool

s = s[target].str.replace('\.','',1)
s
0    1234.5
2    2345.6
dtype: object

然而,我想要的输出是:

0    1234.5
1    123.5
2    2345.6
3    678.9
dtype: object

替换命令和掩码目标似乎正在删除未替换的值,我不知道如何解决这个问题。

【问题讨论】:

    标签: python regex string pandas


    【解决方案1】:

    基于正则表达式的str.replace

    这个带有str.replace 的正则表达式模式应该很好。

    s.str.replace(r'\.(?=.*?\.)', '')
    
    0    1234.5
    1     123.5
    2    2345.6
    3     678.9
    dtype: object
    

    这个想法是,只要有更多的字符要替换,就继续替换。下面是使用的正则表达式的细分。

    \.     # '.'
    (?=    # positive lookahead
    .*?    # match anything
    \.     # look for '.'
    )
    

    np.vectorize 一起玩

    如果您想使用count 做到这一点,这并非不可能,但这是一个挑战。您可以使用np.vectorize 使这更容易。首先,定义一个函数,

    def foo(r, c):
        return r.replace('.', '', c)
    

    矢量化它,

    v = np.vectorize(foo)
    

    现在,调用函数v,传递s 和要替换的计数。

    pd.Series(v(s, s.str.count(r'\.') - 1))
    
    0    1234.5
    1     123.5
    2    2345.6
    3     678.9
    dtype: object
    

    请记住,这基本上是一个美化的循环。


    循环/列表理解

    vectorize 的 python 等效项是,

    r = []
    for x, y in zip(s, s.str.count(r'\.') - 1):
        r.append(x.replace('.', '', y))
    
    pd.Series(r)
    
    0    1234.5
    1     123.5
    2    2345.6
    3     678.9
    dtype: object
    

    或者,使用列表推导:

    pd.Series([x.replace('.', '', y) for x, y in zip(s, s.str.count(r'\.') - 1)])
    
    0    1234.5
    1     123.5
    2    2345.6
    3     678.9
    dtype: object
    

    【讨论】:

    • 所以只要在它之前匹配另一个句点,它就会替换任何句点?我可以在 3 分钟内接受哈哈,你太快了。
    • @seanysull 嗯,有replace 和正则表达式?嗯,无论如何,你需要知道前面是否有一个字符,所以前瞻是无法避免的。
    • 我的意思是没有正则表达式,只使用 str.count 和掩码等
    • @seanysull 我可以完成,但感觉就像从伦敦经过莫斯科到纽约一样。您可以计算每个条目中的点数(比如n),然后用'' 替换它的第一个n-1 实例。
    • @cᴏʟᴅsᴘᴇᴇᴅ 一如既往的出色!
    【解决方案2】:

    您想要替换蒙面的项目并保持其余部分不变。这正是Series.where 所做的,只是它替换了未屏蔽的值,因此您需要取消屏蔽。

    s.where(~target, s.str.replace('\.','',1))
    

    或者您可以通过分配掩码值来就地进行更改,这可能更便宜但具有破坏性。

    s[target] = s[target].str.replace('\.','',1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-08
      • 2018-10-05
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      相关资源
      最近更新 更多