【问题标题】:Pandas extract numbers from column into new columnsPandas 将列中的数字提取到新列中
【发布时间】:2018-09-04 17:59:27
【问题描述】:

我目前有这个 df,其中 rect 列是所有字符串。我需要从中提取 x、y、w 和 h 到单独的列中。数据集非常大,所以我需要一种有效的方法

df['rect'].head()
0    <Rect (120,168),260 by 120>
1    <Rect (120,168),260 by 120>
2    <Rect (120,168),260 by 120>
3    <Rect (120,168),260 by 120>
4    <Rect (120,168),260 by 120>

到目前为止,此解决方案有效,但是您可以看到它非常混乱

df[['x', 'y', 'w', 'h']] = df['rect'].str.replace('<Rect \(', '').str.replace('\),', ',').str.replace(' by ', ',').str.replace('>', '').str.split(',', n=3, expand=True)

有没有更好的方法?可能是正则表达式方法

【问题讨论】:

  • 字符串列是在哪里创建的?
  • 字符串列是在我无权访问的其他函数中创建的,所以我必须从这里开始

标签: python pandas


【解决方案1】:

使用extractall

df[['x', 'y', 'w', 'h']] = df['rect'].str.extractall('(\d+)').unstack().loc[:,0]
Out[267]: 
match    0    1    2    3
0      120  168  260  120
1      120  168  260  120
2      120  168  260  120
3      120  168  260  120
4      120  168  260  120

【讨论】:

  • @ksooklall 是的,快乐的编码
【解决方案2】:

内联

制作副本

df.assign(**dict(zip('xywh', df.rect.str.findall('\d+').str)))

                          rect    x    y    w    h
0  <Rect (120,168),260 by 120>  120  168  260  120
1  <Rect (120,168),260 by 120>  120  168  260  120
2  <Rect (120,168),260 by 120>  120  168  260  120
3  <Rect (120,168),260 by 120>  120  168  260  120
4  <Rect (120,168),260 by 120>  120  168  260  120

或者只是重新分配给df

df = df.assign(**dict(zip('xywh', df.rect.str.findall('\d+').str)))

df

                          rect    x    y    w    h
0  <Rect (120,168),260 by 120>  120  168  260  120
1  <Rect (120,168),260 by 120>  120  168  260  120
2  <Rect (120,168),260 by 120>  120  168  260  120
3  <Rect (120,168),260 by 120>  120  168  260  120
4  <Rect (120,168),260 by 120>  120  168  260  120

就地

修改现有的df

df[[*'xywh']] = pd.DataFrame(df.rect.str.findall('\d+').tolist())

df

                          rect    x    y    w    h
0  <Rect (120,168),260 by 120>  120  168  260  120
1  <Rect (120,168),260 by 120>  120  168  260  120
2  <Rect (120,168),260 by 120>  120  168  260  120
3  <Rect (120,168),260 by 120>  120  168  260  120
4  <Rect (120,168),260 by 120>  120  168  260  120

【讨论】:

  • 您确定*df[[*'xywh']] = ... 中工作。我不断收到SyntaxError: invalid syntax
  • 这是你的 Python 版本。是,我确定。它所做的是将字符串解压缩为列表。您可以使用简单的df[list('xywh')] 或更明确地使用df[['x', 'y', 'w', 'h']] 来做同样的事情
【解决方案3】:

如果字符串遵循特定格式&lt;Rect \((\d+),(\d+)\),(\d+) by (\d+)&gt;,您可以将此正则表达式与str.extract 方法一起使用:

df[['x','y','w','h']] = df.rect.str.extract(r'<Rect \((\d+),(\d+)\),(\d+) by (\d+)>')

df
#                          rect    x    y    w    h
#0  <Rect (120,168),260 by 120>  120  168  260  120
#1  <Rect (120,168),260 by 120>  120  168  260  120
#2  <Rect (120,168),260 by 120>  120  168  260  120
#3  <Rect (120,168),260 by 120>  120  168  260  120
#4  <Rect (120,168),260 by 120>  120  168  260  120

【讨论】:

  • o/@Psidom (-:
【解决方案4】:

使用str.extract,将组从正则表达式提取到列中:

df['rect'].str.extract(r'\((?P<x>\d+),(?P<y>\d+)\),(?P<w>\d+) by (?P<h>\d+)', expand=True)

结果:

     x    y    w    h
0  120  168  260  120
1  120  168  260  120
2  120  168  260  120
3  120  168  260  120
4  120  168  260  120

【讨论】:

    【解决方案5】:

    在这种情况下,“优化”数据本身而不是试图将其转变为消费者想要的东西是有意义的。将干净的数据更改为专用格式比将专用格式更改为可移植的格式要容易得多。

    也就是说,如果你真的必须解析这个,你可以做类似的事情

    >>> import re
    >>> re.findall(r'\d+', '<Rect (120,168),260 by 120>')
    ['120', '168', '260', '120']
    >>>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      相关资源
      最近更新 更多