[英]how to split the data in a column based on multiple delimiters, into multiple columns, in pandas
[英]Pandas: Split columns into multiple columns by two delimiters
我有这样的数据
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
然后再次由=
拆分,但如果我有很多行,尤其是当有很多字段无法预先硬编码时,这似乎效率不高。
任何建议都将受到极大欢迎。
您可以将命名组与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
以获得所需的输出。
### Starting Data
#ID INFO
#1 A=2;B=2;C=5
#2 A=3;B=4;C=1
#3 A=1;B=3;C=2
#4 A=1;C=2
(df.set_index('ID')['INFO']
.str.split(';', expand=True)
.stack()
.str.partition('=')
.reset_index(-1, drop=True)
.pivot(columns=0, values=2)
)
# A B C
#ID
#1 2 2 5
#2 3 4 1
#3 1 3 2
#4 1 NaN 2
浏览系列比遍历数据帧的行要快得多。
所以我会这样做:
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
它应该比拆分两次数据帧列要快。
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)
另一种解决方案是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
另一种解决方案:
#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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.