【问题标题】:Python reformatting strings based on contentsPython 根据内容格式化字符串
【发布时间】:2021-07-14 10:52:19
【问题描述】:

在熊猫数据框中,我的行内容格式如下:

1) abc123-Target 4-ufs
2) abc123-target4-ufs
3) geo.4
4) j123T4

所有这些都应该是:目标 4

到目前为止,我的清洁程序如下:

df["point_id"] = df["point_id"].str.lower()
df["point_id"] = df['point_id'].str.replace('^.*?(?=target)', '')

这会返回:

1) target 4-ufs
2) target4-ufs
3) geo.14
4) geo.2
5) j123T4

我认为我需要的是:

a. Remove anything after the last number in the string, this solves 1
b. If 'target' does not have a space after it add a space, this with the above solves 2
c. If the string ends in a point and a number of any length remove everything before the point (incl. point) and replace with 'target ', this solves 3 and 4
d. If the string ends with a 't' followed by a number of any length remove everything before 't' and replace with 'target ', this solves 5

我正在查看 regex 和 re 但以下内容无效(在最后一个数字前添加空格)

df["point_id"] = re.sub(r'\D+$', '', df["point_id"])

【问题讨论】:

    标签: python-3.x regex python-re


    【解决方案1】:

    阅读规则,您可能会使用 2 个捕获组并检查组值:

    \btarget\s*(\d+)|.*[t.](\d+)$
    
    • \btarget\s*(\d+) 匹配目标、可选空白字符并捕获 group 1 中的 1+ 个数字
    • |或者
    • .*[t.] 匹配 0+ 个字符,后跟 t 或 .
    • (\d+)$ 在字符串末尾的group 2中捕获1+位

    Regex demo | Python demo

    Python 示例:

    import re
    import pandas as pd
    
    pattern = r"\btarget\s*(\d+)|.*[t.](\d+)$"
    strings = [
        "abc123-Target 4-ufs",
        "abc123-target4-ufs",
        "geo.4",
        "j123T4"
    ]
    
    df = pd.DataFrame(strings, columns=["point_id"])
    
    def change(s):
        m = re.search(pattern, s, re.IGNORECASE)
        return "target " + (m.group(2) if m.group(2) else m.group(1))
    
    df["point_id"] = df["point_id"].apply(change)
    print(df)
    

    输出

       point_id
    0  target 4
    1  target 4
    2  target 4
    3  target 4
    

    【讨论】:

      【解决方案2】:

      你可以使用

      df = pd.DataFrame({'point_id':['abc123-Target 4-ufs','abc123-target4-ufs','geo.4','j123T4']})
      df['point_id'] = df['point_id'].str.replace(r'(?i).*Target\s*(\d+).*', r'target \1', regex=True)
      df.loc[df['point_id'].str.contains(r'(?i)\w[.t]\d+$'), 'point_id'] = 'target 4'
      #    point_id
      # 0  target 4
      # 1  target 4
      # 2  target 4
      # 3  target 4
      

      正则表达式是(?i)Target\s*\d+|\w+[.t]\d+$:

      • (?i) - 不区分大小写的匹配
      • .* - 除换行符之外的任何 0+ 个字符,尽可能多
      • Target\s*(\d+).* - Target,零个或多个空格,以及捕获到组 1 中的一个或多个数字
      • .* - 除换行符以外的任何 0+ 个字符,尽可能多

      第二个正则表达式匹配

      • (?i) - 不区分大小写的匹配
      • \w - 一个字字符,然后
      • [.t] - .t 然后
      • \d+$ - 字符串末尾的一位或多位数字。

      第二个正则表达式用作掩码,只要模式与正则表达式匹配,point_id 列中的值就会设置为 target 4

      请参阅 regex #1 demoregex #2 demo

      【讨论】:

      • 不幸的是,这个答案用target 4 覆盖了目标号码,这只是一个例子。 @The Fourth Bird 的回答给出了完整的答案。不过谢谢你的解释,不胜感激。
      • @SpatialDigger 我更新了答案。两行代码解决。
      猜你喜欢
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      相关资源
      最近更新 更多