在 Pandas 数据帧列上使用 Rsplit 根据分隔符的第二个实例进行分离



>我有一个熊猫数据帧的列,我想根据分隔符的第二个实例将其拆分并扩展为一个新的数据帧。我是根据分隔符的最后一个实例进行拆分的,但不幸的是,~80k 行中有少数实例有 4 个"_"而不是 3。

例如,我有一个包含多列的数据帧,其中我想拆分为新数据帧的数据帧如下所示:

df.head()
gene
0  NM_000000_foo_blabla
1  NM_000001_bar

我想拆分和扩展它,使其分离为:

(需要(

df2.head()
col1          col2
0  NM_000000     foo_bar
1  NM_000001     foo

在使用我当前的代码时:

df2 = df['gene'].str.rsplit('_', 1, expand=True).rename(lambda x: f'col{x + 1}', axis=1) 

我明白这个:

(实际(

df2.head()
col1          col2
0  NM_000000_foo bar
1  NM_000001     foo

有没有一种简单的方法可以实现我修改我已经使用的代码行?我尝试在 rsplit 中玩拆分的数量,但无法达到我想要的结果。谢谢!

由于您的数据似乎定义得相当好,因此您可以使用正则表达式在分隔符的第二个实例上进行提取。

df['gene'].str.extract(r'(?:[^_]+_){2}(.*)')

0
0  foo_blabla
1         bar

您可以将其概括为任何分隔符,并使用简单的函数将其匹配任意次数:

def build_regex(delimiter, num_matches=1):
return rf'(?:[^{delimiter}]+{delimiter}){{{num_matches}}}(.*)'
>>> build_regex('_', 2)
'(?:[^_]+_){2}(.*)'
>>> df['gene'].str.extract(build_regex('_', 2))
0
0  foo_blabla
1         bar
>>> df['gene'].str.extract(build_regex('_', 3))
0
0  blabla
1     NaN

正则表达式解释

(?:            # non capture group
[^_]+        # match anything but _ one or more times
_            # match _
){2}           # match this group 2 times
(              # start of capture group 1
.*           # match anything greedily
)              # end of matching group 1

如果不能保证在前两个分隔符中的任何一个之前有文本,您还可以使非断言匹配 0 次或更多次:

(?:[^_]*_){2}(.*)

只需将第二个'_'替换为您的自定义除尘器并在其上split即可

df.gene.str.replace(r'([^_]+_[^_]+)_', r'1|').str.split('|', expand=True)
Out[488]:
0           1
0  NM_000000  foo_blabla
1  NM_000001  bar 

最新更新