【问题标题】:Extract first digit sequence from string containing digits, non-digits and then digits从包含数字、非数字和数字的字符串中提取第一个数字序列
【发布时间】:2019-07-02 20:27:45
【问题描述】:

我在 Pandas 数据框中有一列包含以下值:

111042345--
111042345
110374217dclid=CA-R3K
109202817lciz@MM10082IA

我只需要提取每行中的第一个数字序列 - 而不是该行中的所有数字。所以输出会是这样的:

111042345
111042345 
110374217 
109202817

我认为实现这一目标的最佳方法是按数字拆分字符串并返回,但这会在非数字字符之后给我不需要的数字。

【问题讨论】:

    标签: python-3.x string pandas split


    【解决方案1】:

    使用 str.extract 和正则表达式 \d 提取数字,{,5} 表示前 5 位数字,+ 表示所有数字:

    df['first_5_digits'] = df['Col'].str.extract('(\d{,5})')
    df['all_digits'] = df['Col'].str.extract('(\d+)')
    print (df)
                           Col first_5_digits all_digits
    0              111042345--          11104  111042345
    1                111042345          11104  111042345
    2    110374217dclid=CA-R3K          11037  110374217
    3  109202817lciz@MM10082IA          10920  109202817
    

    像@Jon Clements 指出的也可以通过索引提取 N 个值:

    df['first_5_digits'] = df['Col'].str.extract('(\d+)').str[:5]
    

    【讨论】:

    • 虽然很高兴表明可以告诉正则表达式仅匹配 N 多次出现,但我可能不会在这里使用 extract 两次,而是将其用于 all_digits 然后使用:df['first_5_digits'] = df['all_digits'].str[:5] ...
    • 效果很好,只是将其更改为提取前 9 位数字。谢谢。
    【解决方案2】:

    你可以通过申请itertools.takewhile来解决这个问题:

    在熊猫中:

    data = """111042345--
    111042345
    110374217dclid=CA-R3K
    109202817lciz@MM10082IA""".split()
    
    import pandas as pd
    from itertools import takewhile
    
    df = pd.DataFrame(data)
    
    df["numbers"] = df[0].apply(lambda x:''.join(takewhile(str.isdigit,x)) )
    print(df)
    

    输出(熊猫):

                             0    numbers
    0              111042345--  111042345
    1                111042345  111042345
    2    110374217dclid=CA-R3K  110374217
    3  109202817lciz@MM10082IA  109202817
    

    对于普通列表:

    data = """111042345--
    111042345
    110374217dclid=CA-R3K
    109202817lciz@MM10082IA""".split()
    
    print(data)
    
    from itertools import takewhile
    
    d = [ ''.join(takewhile(str.isdigit,text)) for text in data]
    
    print(d)
    

    输出(简单列表):

    # splitted data
    ['111042345--', '111042345', '110374217dclid=CA-R3K', '109202817lciz@MM10082IA']
    
    # itertools.takewhile
    ['111042345', '111042345', '110374217', '109202817']
    

    边缘情况:


    Scott Boston 建议,因为更高效:

    df["faster numbers"] = [''.join(takewhile(str.isdigit,i)) for i in df[0]]´
    

    (类似的输出 - 其他列标题)

    【讨论】:

    • 在 pandas 中,这比使用 apply 快得多,df[1] = [''.join(takewhile(str.isdigit,i)) for i in df[0]]
    • @ScottBoston 我相信你的话,我是一只熊猫宝宝;)
    【解决方案3】:

    可以用正则解决:

    import re
    data = """111042345--
    111042345
    110374217dclid=CA-R3K
    109202817lciz@MM10082IA""".split()
    output = "\n".join([re.findall('\d+', str(d))[0] for d in data])
    print(output)
    

    输出:

    111042345
    111042345
    110374217
    109202817
    

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 1970-01-01
      • 2018-12-18
      • 1970-01-01
      相关资源
      最近更新 更多