如何在熊猫数据框单元格中提取部分字符串并在其中创建一个包含该字符串的新列

Posted

技术标签:

【中文标题】如何在熊猫数据框单元格中提取部分字符串并在其中创建一个包含该字符串的新列【英文标题】:How to extract part of a string in pandas dataframe cell and create a new column with that string inside it 【发布时间】:2020-12-30 00:39:24 【问题描述】:

我有一个数据框,其中一列包含一个冗长的字符串,其中包含大量信息,我需要将这些信息分成单独的列并将它们添加到数据框中。它类似于How to add a new column with multiple string contain conditions in python pandas other than using np.where?,但我不知道如何适应它。

我可以创建空列,但我不知道字符串是否可以提取元素或者是否可以将其分成列。

例如数据行

0    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs

期望的输出

行号、伏特、Wfm、Sclk、图像、段

1、17、BF27、100、1in24、24

数据

                                              Comments  Image
0    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs      0
1    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs      0
2    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs      0
3    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs      0
4    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs      0
..                                                 ...    ...
706  Row 2 Ch475 Vi 17.5V BF27 Sclk 100ns 1in24 24segs      0
707  Row 2 Ch475 Vi 17.5V BF27 Sclk 100ns 1in24 24segs      0
708  Row 2 Ch475 Vi 17.5V BF27 Sclk 100ns 1in24 24segs      0
709  Row 2 Ch475 Vi 17.5V BF27 Sclk 100ns 1in24 24segs      0
710  Row 2 Ch475 Vi 17.5V BF27 Sclk 100ns 1in24 24segs      0

代码

import pandas as pd
import numpy as np

path = "/Users/.../Desktop/tk_gui_grid/"
file = "orig_data.txt"
filepath = path+file

df = pd.read_csv(filepath, sep='\t', lineterminator='\r')

com = df.loc[:,['Comments']]
dfLen = len(com)

image = [0]*dfLen
com['Image'] = image

print(com)

【问题讨论】:

Here are the pandas docs 关于正则表达式提取。看看这是否有帮助。使用expand 参数会将命名组提取到该名称的列中。 我让这个工作 df['Image']=df['Comments'].str.extract(r'(1in24)') 看起来我需要组合多个正则表达式,我只看了一些与此类似的问题,它看起来像 gobbledygook - 可能需要周末才能弄清楚。 不用担心。我现在为你准备一些东西。 我认为你根本不需要正则表达式。使用expand=True 拆分空格上的字符串并处理要保留的列,删除不需要的列 【参考方案1】:

这是一个使用带有命名捕获组的正则表达式的快速解决方案。

正则表达式优于split:

有些人评论说不需要正则表达式,这是一个真实的陈述。但是,从数据验证的角度来看,使用正则表达式有助于防止“杂散”数据潜入。使用“盲”split() 函数将数据拆分为(一个字符);但是如果源数据发生了变化怎么办?split 函数对此视而不见。然而,使用正则表达式将有助于突出问题,因为模式根本不匹配。是的,您可能会收到一条错误消息 - 但这是一件好事,因为您会收到有关数据格式更改的警报,从而提供解决问题或更新正则表达式模式的机会。

源数据:

为演示模拟了其他行。

0    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in24 24segs
1    Row 2 Ch475 Vi 17.1V BF27 Sclk 101ns 1in24 25segs
2    Row 3 Ch475 Vi 17.2V BF27 Sclk 102ns 1in24 26segs
3    Row 4 Ch475 Vi 17.3V BF27 Sclk 103ns 1in24 27segs
4    Row 5 Ch475 Vi 17.4V BF27 Sclk 104ns 1in24 28segs

代码:

import pandas as pd
import re

path = './orig_data.txt'
cols = ['rownumber', 'volts', 'wfm', 'sclk', 'image', 'segment']
exp = re.compile(r'^\d+\s+Row\s'
                 r'(?P<rownumber>\d+).*\s'
                 r'(?P<volts>\d+\.\d+)V\s'
                 r'(?P<wfm>\w+)\sSclk\s'
                 r'(?P<sclk>\d+)ns\s'
                 r'(?P<image>\w+)\s'
                 r'(?P<segment>\d+)segs.*$')

df = pd.read_csv(path, sep='|', header=None, names=['comment'])
df[cols] = df['comment'].str.extract(exp, expand=True)

输出:

                                             comment rownumber volts   wfm  \
0  0    Row 1 Ch475 Vi 17.0V BF27 Sclk 100ns 1in2...         1  17.0  BF27   
1  1    Row 2 Ch475 Vi 17.1V BF27 Sclk 101ns 1in2...         2  17.1  BF27   
2  2    Row 3 Ch475 Vi 17.2V BF27 Sclk 102ns 1in2...         3  17.2  BF27   
3  3    Row 4 Ch475 Vi 17.3V BF27 Sclk 103ns 1in2...         4  17.3  BF27   
4  4    Row 5 Ch475 Vi 17.4V BF27 Sclk 104ns 1in2...         5  17.4  BF27   

  sclk  image segment  
0  100  1in24      24  
1  101  1in24      25  
2  102  1in24      26  
3  103  1in24      27  
4  104  1in24      28

【讨论】:

我从 Packt 买了一本关于掌握 python 正则表达式的书,因为我从未见过像你在 exp 块中的代码,我认为学习正则表达式会很困难但值得,谢谢S3DEV 我发现我需要更改的内容,我在文本文件中的数据在评论字段中的“行”汽车之前没有任何汽车,一旦我将它从您的 exp 块的第一行中取出这一切都完美无缺。看了第一章有收获,谢谢S3DEV 非常好,很高兴听到它对您有用,甚至更高兴听到您能够调试表达式以删除前导空格。干得好!如果您经常处理文本,您肯定会感谢自己掌握了正则表达式。 Here is a site我经常用来调试表达式。【参考方案2】:

您需要将 Series obj 转换为字符串,然后将其拆分。之后,您可以通过其索引访问每个元素

df['Comments'].str.split(' ')

0    [Row, 1, Ch475, Vi, 17.0V, BF27, Sclk, 100ns, ...

df['Comments'].str.split(' ').str[0]

Out[7]: 
0    Row

df['Comments'].str.split(' ').str[4]

Out[8]: 
0    17.0V

如果您了解如何从拆分中访问每一列,则可以将其分配给数据框中的新行,例如:

df['RowNumber'] = df['Comments'].str.split(' ').str[1]
df['Volts'] = df['Comments'].str.split(' ').str[4]

【讨论】:

以上是关于如何在熊猫数据框单元格中提取部分字符串并在其中创建一个包含该字符串的新列的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫数据框单元格中插入列表

将熊猫数据框单元格中的字典解析为新行单元格(新列)

根据“如果单元格中的字符串”条件删除熊猫列中的行

过滤单元格中有数组的熊猫数据框

熊猫将非空值从行中获取到一个单元格中[重复]

熊猫从数据框中的一列中提取部分字符串并将其存储在一个新列中