在同一行中来自不同列的值上拆分一个Pandas列?

时间:2019-12-10 03:58:55

标签: regex pandas

我有一些DataFrame:

df = pd.DataFrame({'columnA': ['apple', 'banana', 'peach', 'pear'], 'columnB': ['XAXappleYBY', 'ZZZbananaRDESWA', 'HDJFpeachIUYTA', 'POIUYpearMNBV']})

    columnA columnB
0   apple   XAXappleYBY
1   banana  ZZZbananaRDESWA
2   peach   HDJFpeachIUYTA
3   pear    POIUYpearMNBV

我想在columnB中的字符串上分割columnA并展开,例如:

    columnA columnB left_split  right_split
0   apple   XaXappleYBY XaX YBY
1   banana  ZZZbananaRDESWa ZZZ RDESWa
2   peach   HDJFpeachIUYTA  HDJF    IUYTA
3   pear    POIUYpearMNBV   POIUY   MNBV

我该怎么做?

4 个答案:

答案 0 :(得分:2)

使用字符串split和listcomp并构造数据帧df1。最后,回到df

cols = ['columnA', 'columnB']
df1 = pd.DataFrame([x.split(pat) for pat, x in  zip(*map(df.get, cols))], 
                    columns=['left_split', 'right_split'])
df_final = df.join(df1)

Out[153]:
  columnA          columnB left_split right_split
0   apple      XAXappleYBY        XAX         YBY
1  banana  ZZZbananaRDESWA        ZZZ      RDESWA
2   peach   HDJFpeachIUYTA       HDJF       IUYTA
3    pear    POIUYpearMNBV      POIUY        MNBV

[x.split(pat) for pat, x in zip(*map(df.get, cols))]上的说明:

在这种情况下,

zip(*map(df.get, cols))只是zip(df.columnA, df.columnB)的另一种书写方式。在具有许多列的数据框上很方便。使用zip-map版本只是我的习惯:)

[x.split(pat) for pat, x in  zip(*map(df.get, cols))]

Out[198]: [['XAX', 'YBY'], ['ZZZ', 'RDESWA'], ['HDJF', 'IUYTA'], ['POIUY', 'MNB']]

[x.split(pat) for pat, x in  zip(df.columnA, df.columnB)]

Out[199]: [['XAX', 'YBY'], ['ZZZ', 'RDESWA'], ['HDJF', 'IUYTA'], ['POIUY', 'MNBV']]

它压缩2列。在列表理解的每次迭代中,它对每一列的对应值进行切片。也就是说,在每次迭代中,它会切片与columnAcolumnB的每一行相对应的元组。每个元组都被解包到patx,其中patcolumnA的值,而xcolumnB的值。 x是您要分割的字符串,因此调用x.split(pat)会将columnB的每个字符串除以pat的每个columnA

答案 1 :(得分:2)

IIUC,您可以使用:

regpattern = '|'.join(df['columnA'])

df[['left_split','right_split']]=df['columnB'].str.split(regpattern, expand=True)

print(df)

输出:

  columnA          columnB left_split right_split
0   apple      XAXappleYBY        XAX         YBY
1  banana  ZZZbananaRDESWA        ZZZ      RDESWA
2   peach   HDJFpeachIUYTA       HDJF       IUYTA
3    pear    POIUYpearMNBV      POIUY        MNBV

答案 2 :(得分:1)

我想,也许可以看看这个简单的表达式:

^([A-Z]*)([a-z]*)([A-Z]*)

RegEx Demo

测试

import pandas as pd

df = pd.DataFrame({'columnA': ['apple', 'banana', 'peach', 'pear'], 'columnB': [
                  'XAXappleYBY', 'ZZZbananaRDESWA', 'HDJFpeachIUYTA', 'POIUYpearMNBV']})


df['left_split'] = df['columnB'].str.replace(r'^([A-Z]*)([a-z]*)([A-Z]*)', r'\1')
df['right_split'] = df['columnB'].str.replace(r'^([A-Z]*)([a-z]*)([A-Z]*)', r'\3')
print(df)

输出

  columnA          columnB left_split right_split
0   apple      XAXappleYBY        XAX         YBY
1  banana  ZZZbananaRDESWA        ZZZ      RDESWA
2   peach   HDJFpeachIUYTA       HDJF       IUYTA
3    pear    POIUYpearMNBV      POIUY        MNBV

如果您想简化/更新/探索表达式,请在regex101.com的右上角进行解释。如果您有兴趣,可以观看匹配的步骤或在this debugger link中进行修改。调试器演示了a RegEx engine如何逐步使用一些示例输入字符串并执行匹配过程的过程。


RegEx电路

jex.im可视化正则表达式:

enter image description here

答案 3 :(得分:0)

\d+\s+(?<fruit>\w+)\s+\w+(?<middle>\k<fruit>)\w+

this luminance formula

输入是没有第一行(标题)的表,找到已命名的组“ middle”,并根据需要将其替换为空字符。

说明:

\d+\s+找到前导数字和空格
(?<fruit>\w+)找到您要用于分割的水果,并将该组命名为“水果”。
w+(?<middle>\k<fruit>)\w+使用先前命名的“水果”作为匹配条件,并将匹配的组命名为“中间”