我有这样的数据
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
然后再用=
分割,但是在我有很多行的情况下,尤其是在有太多无法事先进行硬编码的字段时,这似乎不太有效。
任何建议都将受到欢迎。
答案 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