【问题标题】:Change last word after space in a dafaframe column更改数据框列中空格后的最后一个单词
【发布时间】:2021-04-11 06:09:41
【问题描述】:

我正在处理一个包含计算机名称的数据框,并且我正在尝试匿名化计算机名称。这是我正在使用的数据框的示例

df = pd.DataFrame({'id': [1, 2, 3, 4, 5], 'computer_name': [u'LENOVO 09 X32H0GB', u'LENOVO vmhsbpmh613.xyz.biz', u'Dell Inc. PowerEdge R910 XKF2S75', u'HP  ppesfesxb203.corp.123.com', 'IBM SoftLayer 13 L89P4567']})

这是匿名化所需的内容。

  1. 从 RIGHT 中的第一个 SPACE 之后,从 RIGHT 中选择第一组字符串 .. 例如:对于“LENOVO vmhsbpmh613.xyz.biz”,它将是“vmhsbpmh613.xyz.biz”

  2. 在从右侧获取第一组字符串后,例如“vmhsbpmh613.xyz.biz”,从第一个点 (.) 中删除所有字符,这将给出“vmhsbpmh613”,如果没有点(.),则保留仅最后一组字符串,请注意,仅从右侧的第一组字符串中删除点 (.) 之后的字符串很重要,否则就像本例中的“Dell Inc. PowerEdge R910 XKF2S75”一样,它将导致删除所有内容在点“戴尔公司”之后

  3. 最后将前 3 个字符替换为 xxx ,例如 xxxsbpmh613

这是输出的样子

df = pd.DataFrame({'id': [1, 2, 3, 4, 5], 'computer_name': [u'LENOVO 09 xxxH0GB', u'LENOVO xxxsbpmh613', u'Dell Inc. PowerEdge R910 xxx2S75', u'HP  xxxsfesxb203', 'IBM SoftLayer 13 xxxP4567']})

希望我能够清楚地表达需求,谢谢。

【问题讨论】:

    标签: python pandas python-re


    【解决方案1】:

    Series.str.replace

    df['computer_name'].str.replace(r'\S{3}(\S+?)(?:\.\S+|$)', r'xxx\1')
    

    0                   LENOVO 09 xxxH0GB
    1                  LENOVO xxxsbpmh613
    2    Dell Inc. PowerEdge R910 xxx2S75
    3                    HP  xxxsfesxb203
    4           IBM SoftLayer 13 xxxP4567
    Name: computer_name, dtype: object
    

    正则表达式详细信息

    • \S{3} :完全匹配任何非空白字符 3 次。
    • (\S+?) :捕获组匹配任何非空白字符 1 到无限次,但尽可能少(惰性匹配)
    • (?: : 非捕获组的开始
    • \. :匹配 . 字符
    • \S+ : 计算任何非空白字符
    • $ : 在行尾断言位置
    • ) : 非捕获组结束

    regex demo

    【讨论】:

    • 谢谢@tdy 我不确定它是否更好,但我仍在努力改进模式,有很多极端情况下这种模式会失败:-)
    • @Shubham,这行得通,谢谢……你介意解释一下正则表达式吗……这对我的学习很有帮助
    【解决方案2】:

    第一个rsplit()从右边第一个空格分割:

    s = df.computer_name.str.rsplit(n=1, expand=True)
    
    #                           0                          1
    # 0                 LENOVO 09                    X32H0GB
    # 1                    LENOVO        vmhsbpmh613.xyz.biz
    # 2  Dell Inc. PowerEdge R910                    XKF2S75
    # 3                       HP   ppesfesxb203.corp.123.com
    # 4          IBM SoftLayer 13                   L89P4567
    

    然后split() 在第一个点上,replace() 在前三个字符上加上xxx

    s[1] = s[1].str.split('.', n=1).str[0].replace(r'^...', 'xxx', regex=True)
    
    #                           0             1
    # 0                 LENOVO 09       xxxH0GB
    # 1                    LENOVO   xxxsbpmh613
    # 2  Dell Inc. PowerEdge R910       xxx2S75
    # 3                       HP   xxxsfesxb203
    # 4          IBM SoftLayer 13      xxxP4567
    

    并通过重新组合拆分来完成:

    df.computer_name = s[0] + ' ' + s[1]
    
    #    id                     computer_name
    # 0   1                 LENOVO 09 xxxH0GB
    # 1   2                LENOVO xxxsbpmh613
    # 2   3  Dell Inc. PowerEdge R910 xxx2S75
    # 3   4                  HP  xxxsfesxb203
    # 4   5         IBM SoftLayer 13 xxxP4567
    

    【讨论】:

    • 好用 split :)
    【解决方案3】:

    这听起来像是正则表达式的工作。以下是一些选项:

    # select all chars until reaching a period
    df['computer_name'].str.extract('([^.]*)')
    
    # alternatively, replace all chars after a period with an empty string (delete it)
    df['computer_name'].str.replace('\..*','')
    
    # For your 3rd requirement, select all non space chars at the end of a string and format the result using match groups.
    df['computer_name'].str.replace('([^\s]{3})([^\s]*$)', r'xxx\2',)
    
    

    【讨论】:

    • @ Royce,谢谢,它几乎成功了......唯一的问题是第 3 行,“Dell Inc. PowerEdge R910 XKF2S75”,它给出了“Dell xxx”,我需要“Dell Inc. PowerEdge R910 xxx2S75",就像我在问题的第 2 点中提到的那样
    猜你喜欢
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 2021-12-02
    • 2019-10-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    相关资源
    最近更新 更多