爆炸熊猫数据框列
Posted
技术标签:
【中文标题】爆炸熊猫数据框列【英文标题】:exploding a pandas dataframe column 【发布时间】:2019-01-15 12:09:37 【问题描述】:我有一个看起来像这样的 Pandas 数据框:
text = ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz"]
labels = ["label_1, label_2",
"label_1, label_3, label_2",
"label_2, label_4",
"label_1, label_2, label_5",
"label_2, label_3",
"label_3, label_5, label_1, label_2",
"label_1, label_3"]
df = pd.DataFrame(dict(text=text, labels=labels))
df
text labels
0 abcd label_1, label_2
1 efgh label_1, label_3, label_2
2 ijkl label_2, label_4
3 mnop label_1, label_2, label_5
4 qrst label_2, label_3
5 uvwx label_3, label_5, label_1, label_2
6 yz label_1, label_3
我想把数据框格式化成这样:
text label_1 label_2 label_3 label_4 label_5
abcd 1.0 1.0 0.0 0.0 0.0
efgh 1.0 1.0 1.0 0.0 0.0
ijkl 0.0 1.0 0.0 1.0 0.0
mnop 1.0 1.0 0.0 0.0 1.0
qrst 0.0 1.0 1.0 0.0 0.0
uvwx 1.0 1.0 1.0 0.0 1.0
yz 1.0 0.0 1.0 0.0 0.0
我怎样才能做到这一点?
(我知道我可以拆分标签中的字符串并将它们转换为列表,方法是执行df.labels.str.split(",")
之类的操作,但不确定如何从那里继续。
(所以基本上我想将标签列中的这些关键字转换为自己的列,并在它们出现在预期输出中时填写 1)
【问题讨论】:
标签列中的值是否有最大数量? @MohitMotwani 不,它不是固定的,它可能会有所不同。 pandas: How do I split text in a column into multiple rows?的可能重复 @MohitMotwani 我试过了,它没有产生所需的解决方案 【参考方案1】:如果列数是动态的,这将有助于找到可能的列。
unique = df['labels'].apply(lambda x: x.split(", ")).values.tolist()
unique = [i for sublist in unique for i in sublist]
unique = set(unique)
因此,现在是独一无二的。 'label_1'、'label_2'、'label_3'、'label_4'、'label_5'
max_label = len(unique)
这将为我们提供最大的列数。
回答
def labeller(labels):
value = [0] * max_label
for label in labels:
value[int(label[-1])-1] = 1
return value
df['labels'] = df['labels'].apply(lambda x: x.split(", ")).apply(labeller)
df[['label_' + str(i+1) for i in range(max_label)]] = df.labels.apply(pd.Series)
df.drop(['labels'], axis=1, inplace=True)
text label_1 label_2 label_3 label_4 label_5
0 abcd 1 1 0 0 0
1 efgh 1 1 1 0 0
2 ijkl 0 1 0 1 0
3 mnop 1 1 0 0 1
4 qrst 0 1 1 0 0
5 uvwx 1 1 1 0 1
6 yz 1 0 1 0 0
【讨论】:
【参考方案2】:代码:
text = ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz"]
labels = ["label_1, label_2",
"label_1, label_3, label_2",
"label_2, label_4",
"label_1, label_2, label_5",
"label_2, label_3",
"label_3, label_5, label_1, label_2",
"label_1, label_3"]
df = pd.DataFrame(dict(text=text, labels=labels))
df = df.drop('labels', axis=1).join(
df.labels
.str
.split(', ', expand=True)
.stack()
.reset_index(drop=True, level=1)
.rename('labels')
)
df['value'] = 1
df_new = df.pivot(values = 'value', index='text', columns = 'labels').fillna(0)
print(df_new)
输出:
labels text label_1 label_2 label_3 label_4 label_5
0 abcd 1.0 1.0 0.0 0.0 0.0
1 efgh 1.0 1.0 1.0 0.0 0.0
2 ijkl 0.0 1.0 0.0 1.0 0.0
3 mnop 1.0 1.0 0.0 0.0 1.0
4 qrst 0.0 1.0 1.0 0.0 0.0
5 uvwx 1.0 1.0 1.0 0.0 1.0
6 yz 1.0 0.0 1.0 0.0 0.0
在这个主要的事情是拆分使用 (,
) 与空间,因为你的字符串格式,如果你改变该格式而不是使用适当的拆分。
例如:
如果您像这样使用带有单个逗号的拆分
df = df.drop('labels', axis=1).join(
df.labels
.str
.split(',', expand=True)
.stack()
.reset_index(drop=True, level=1)
.rename('labels')
)
那么您将需要额外的代码来删除空格
df['labels'] = df['labels'].str.replace(" ", "")
其余代码将相同。
【讨论】:
【参考方案3】:一个简单的解决方案是使用pd.get_dummies
,如下所示:
pd.get_dummies(
df.set_index('text')['labels'].str.split(', ', expand=True).stack()
).groupby('text').sum()
【讨论】:
【参考方案4】:您可以使用pd.Series.str.get_dummies
并与text
系列结合使用:
dummies = df['labels'].str.replace(' ', '').str.get_dummies(',')
res = df['text'].to_frame().join(dummies)
print(res)
text label_1 label_2 label_3 label_4 label_5
0 abcd 1 1 0 0 0
1 efgh 1 1 1 0 0
2 ijkl 0 1 0 1 0
3 mnop 1 1 0 0 1
4 qrst 0 1 1 0 0
5 uvwx 1 1 1 0 1
6 yz 1 0 1 0 0
【讨论】:
以上是关于爆炸熊猫数据框列的主要内容,如果未能解决你的问题,请参考以下文章