熊猫:使用两个定界符将列拆分为多列

时间:2020-03-23 17:46:14

标签: python pandas

我有这样的数据

ID   INFO
1    A=2;B=2;C=5
2    A=3;B=4;C=1
3    A=1;B=3;C=2

我想将“信息”列拆分为

ID   A    B    C
1    2    2    5
2    3    4    1
3    1    3    2

我可以通过使用一个分隔符来拆分列

df['A'], df['B'], df['C'] = df['INFO'].str.split(';').str

然后再用=分割,但是在我有很多行的情况下,尤其是在有太多无法事先进行硬编码的字段时,这似乎不太有效。

任何建议都将受到欢迎。

5 个答案:

答案 0 :(得分:3)

您可以将命名组与Series.str.extract一起使用。最后,连接'ID'。假设您总是在一行中有A =; B =;和C =。

pd.concat([df['ID'], 
           df['INFO'].str.extract('A=(?P<A>\d);B=(?P<B>\d);C=(?P<C>\d)')], axis=1)

#   ID  A  B  C
#0   1  2  2  5
#1   2  3  4  1
#2   3  1  3  2

如果您想要一种更灵活的解决方案来处理单行可能为'A=1;C=2'的情况,那么我们可以在';'partition上进行拆分。最后使用'='获得所需的输出。

pivot

答案 1 :(得分:3)

浏览系列比遍历数据帧的行要快得多。

所以我会这样做:

pd.DataFrame([dict([x.split('=') for x in t.split(';')]) for t in df['INFO']], index=df['ID']).reset_index()

它给出了预期的结果:

   ID  A  B  C
0   1  2  2  5
1   2  3  4  1
2   3  1  3  2

它应该比拆分两次数据框列更快。

答案 2 :(得分:2)

values = [dict(item.split("=") for item in value.split(";")) for value in df.INFO]
df[['a', 'b', 'c']] = pd.DataFrame(values)

这将为您提供所需的输出:

    ID INFO         a   b   c
    1  a=1;b=2;c=3  1   2   3
    2  a=4;b=5;c=6  4   5   6
    3  a=7;b=8;c=9  7   8   9

说明: 第一行将每个值转换为字典。 例如

x = 'a=1;b=2;c=3' 
dict(item.split("=") for item in x.split(";"))  

结果: {'a': '1', 'b': '2', 'c': '3'}

DataFrame可以将字典列表作为输入并将其转换为数据框。

然后,您只需要将数据框分配给所需的列:
df[['a', 'b', 'c']] = pd.DataFrame(values)

答案 3 :(得分:2)

另一种解决方案是Series.str.findAll提取值,然后提取apply(pd.Series)

df[["A", "B", "C"]] = df.INFO.str.findall(r'=(\d+)').apply(pd.Series)
df = df.drop("INFO", 1)

详细信息:

df = pd.DataFrame([[1, "A=2;B=2;C=5"],
                [2, "A=3;B=4;C=1"],
                [3, "A=1;B=3;C=2"]],
                 columns=["ID", "INFO"])

print(df.INFO.str.findall(r'=(\d+)'))
# 0    [2, 2, 5]
# 1    [3, 4, 1]
# 2    [1, 3, 2]

df[["A", "B", "C"]] = df.INFO.str.findall(r'=(\d+)').apply(pd.Series)
print(df)
#    ID         INFO  A  B  C
# 0   1  A=2;B=2;C=5  2  2  5
# 1   2  A=3;B=4;C=1  3  4  1
# 2   3  A=1;B=3;C=2  1  3  2

# Remove INFO column
df = df.drop("INFO", 1)
print(df)
#    ID  A  B  C
# 0   1  2  2  5
# 1   2  3  4  1
# 2   3  1  3  2

答案 4 :(得分:1)

另一种解决方案:

  #split on ';'
  #explode
  #then split on '='
  #and pivot
  df_INFO = (df.INFO
             .str.split(';')
             .explode()
             .str.split('=',expand=True)
             .pivot(columns=0,values=1)
             )

   pd.concat([df.ID,df_INFO],axis=1)

    ID  A   B   C
0   1   2   2   5
1   2   3   4   1
2   3   1   3   2