熊猫:如何从另一个字符串中提取一个字符串

时间:2020-09-22 09:05:03

标签: python pandas

我有一列包含8000行的列,我需要创建一个新列,该列的值将从现有列中提取。

字符串显示如下:

TP-ETU06-01-525-W-133

我想从该字符串中创建两个新列,其中从第二个字符串ETU06中提取第一个新列的值,第二个从最后一个字符串133中提取第二个。

我通过使用以下方式完成此操作:

df["sys_no"] = df.apply(lambda x:x["test_no"].split("-")[1] if (pd.notnull(x["test_no"]) and x["test_no"]!="" and len(x["test_no"].split("-"))>0) else None,axis=1)

df["package_no"] = df.apply(lambda x:x["test_no"].split("-")[-1] if (pd.notnull(x["test_no"]) and x["test_no"]!="" and len(x["test_no"].split("-"))>0) else None,axis=1)

它实际上可以正常工作,但是现有的列具有不跟随其他列的随机字符串。因此,如果出现随机字符串,我想在新列中保留空白。

我应该如何更改脚本?

谢谢

2 个答案:

答案 0 :(得分:1)

使用Series.str.contains作为掩码,然后将值除以Series.str.split,并通过按掩码仅索引已过滤的行来选择第二和最后一个值:

print (df)
                 test_no
0              temp data
1                    NaN
2  TP-ETU06-01-525-W-133

mask = df["test_no"].str.contains('-', na=False)
splitted = df["test_no"].str.split("-")
df.loc[mask, "sys_no"] = splitted[mask].str[1]
df.loc[mask, "package_no"] = splitted[mask].str[-1]
print (df)
                 test_no sys_no package_no
0              temp data    NaN        NaN
1                    NaN    NaN        NaN
2  TP-ETU06-01-525-W-133  ETU06        133

    

答案 1 :(得分:1)

此方法使用 regex 和命名的捕获组,仅用两行代码即可找到并提取感兴趣的字符串。

正则表达式对split的好处:

确实不需要正则表达式。但是,从数据验证的角度来看,使用正则表达式有助于防止“杂散”数据蔓延。使用“盲” split()函数可将数据分割为(一个字符)。但是如果源数据已更改怎么办?拆分功能对此无视。鉴于使用正则表达式将有助于突出显示问题,因为模式根本不匹配。是的,您可能会收到一条错误消息-但这是一件好事,因为您会收到有关数据格式更改的警报,从而有机会解决此问题或更新正则表达式模式。

此外,正则表达式提供了一种可靠的解决方案,因为该模式与整个字符串匹配,并且该模式之外的任何内容都将被忽略-就像问题中提到的示例一样。

如果您想对正则表达式模式本身进行一些解释,只需添加一条注释,我将更新答案进行解释。

样本数据:

                 test_no
0  TP-ETU05-01-525-W-005
1  TP-ETU06-01-525-W-006
2  TP-ETU07-01-525-W-007
3  TP-ETU08-01-525-W-008
4  TP-ETU09-01-525-W-009
5                    NaN
6                    NaN
7             otherstuff

代码:

import re

exp = re.compile(r'^[A-Z]{2}-(?P<sys_no>[A-Z]{3}\d{2})-\d{2}-\d{3}-[A-Z]-(?P<package_no>\d{3})$')
df[['sys_no', 'package_no']] = df['test_no'].str.extract(exp, expand=True)

输出:

                 test_no  sys_no package_no
0  TP-ETU05-01-525-W-005   ETU05        005
1  TP-ETU06-01-525-W-006   ETU06        006
2  TP-ETU07-01-525-W-007   ETU07        007
3  TP-ETU08-01-525-W-008   ETU08        008
4  TP-ETU09-01-525-W-009   ETU09        009
5                    NaN     NaN        NaN
6                    NaN     NaN        NaN
7             otherstuff     NaN        NaN
相关问题