我有一个如下数据框:
data = {'name': {0: 'mypath\\is\this', 1: 'mynewpath\\is\this'},
'vals': {0: [{'name1': 'val1'}, {'name2': 'val2'}, {'name3': 'val3'}],
1: [{'name1': 'val1'}, {'name2': 'val2'}, {'name3': 'val3'}]}}
df = pd.DataFrame(data)
name vals
mypath\is\this [{name1:val1},{name2:val2},{name3:val3}]
mynewpath\is\this [{name1:val1},{name2:val2},{name3:val3}]
如何展开values列并将键映射到创建新名称,以保持与其相关的值。
预期输出如下:
name vals
mypath\is\this\name1 val1
mypath\is\this\name2 val2
mypath\is\this\name3 val3
mynewpath\is\this\name1 val1
mynewpath\is\this\name2 val2
mynewpath\is\this\name3 val3
答案 0 :(得分:1)
首先使用最少示例的解决方案:
import pandas as pd
df = pd.DataFrame({
"name": ["mypath\is\this", "mynewpath\is\this"],
"vals":[[{"name1":"val1"},{"name2":"val2"},{"name3":"val3"}], [{"name1":"val1"},{"name2":"val2"},{"name3":"val3"}]]
})
解决方案包括将每个行中的dict列表拆分为带有该段代码的DataFrame:
df = pd.DataFrame({
"name":
row["name"],
"key": [element for d in row["vals"] for element in list(d.keys())],
"value":
[element for d in row["vals"] for element in list(d.values())]
})
然后juste concatenate
并操纵字符串以获得所需的输出。
这里有完整的代码:
df = pd.concat([
pd.DataFrame({
"name":
row["name"],
"key": [element for d in row["vals"] for element in list(d.keys())],
"value":
[element for d in row["vals"] for element in list(d.values())]
}) for index, row in df.iterrows()
])
df["name"] = df["name"] + "\\" + df["key"]
df = df.drop("key", axis=1)
注1:我放\\
因为\
是一个espace字符。
注2:我使用list comprehension迭代数据帧的行,这样可以更容易地连接所有数据帧。
答案 1 :(得分:1)
我真的想尝试一下矢量化解决方案。但是df.vals
是一系列的词汇而不仅仅是一系列的词汇让我失望。希望我们看到其他一些人有更好的解决方案。
在最上面的列表中,这是我设法得到的。你可能会发现它很有用。请注意,这并没有利用矢量化,因为我在行轴上使用了apply。
>>> df
name vals
0 mypath\is\this [{'name1': 'val1'}, {'name2': 'val2'}, {'name3...
1 mynewpath\is\this [{'name1': 'val1'}, {'name2': 'val2'}, {'name3...
>>> def explode_column(row):
... for column in row.vals:
... for key,value in column.items():
... row[key] = value
... return row
...
>>> exploded_df = df.apply(explode_column, axis=1)
>>> exploded_df
name vals name1 name2 name3
0 mypath\is\this [{'name1': 'val1'}, {'name2': 'val2'}, {'name3... val1 val2 val3
1 mynewpath\is\this [{'name1': 'val1'}, {'name2': 'val2'}, {'name3... val1 val2 val3
>>> melted_df = exploded_df.melt(id_vars=['name'], value_vars=['name1', 'name2', 'name3'])
>>> melted_df
name variable value
0 mypath\is\this name1 val1
1 mynewpath\is\this name1 val1
2 mypath\is\this name2 val2
3 mynewpath\is\this name2 val2
4 mypath\is\this name3 val3
5 mynewpath\is\this name3 val3
>>> melted_df['new_name'] = melted_df.name.str.cat(melted_df.variable, sep="\\")
>>> melted_df
name variable value new_name
0 mypath\is\this name1 val1 mypath\is\this\name1
1 mynewpath\is\this name1 val1 mynewpath\is\this\name1
2 mypath\is\this name2 val2 mypath\is\this\name2
3 mynewpath\is\this name2 val2 mynewpath\is\this\name2
4 mypath\is\this name3 val3 mypath\is\this\name3
5 mynewpath\is\this name3 val3 mynewpath\is\this\name3
答案 2 :(得分:1)
因为我们将Python对象作为值,所以矢量化解决方案似乎不可行。使用列表理解是有道理的:
df = pd.DataFrame([('\\'.join((r[1]['name'], list(x.keys())[0])), list(x.values())[0])
for r in df.iterrows() for x in r[1]['vals']], columns=['name', 'vals'])
print(df)
输出:
name vals
0 mypath\is\this\name1 val1
1 mypath\is\this\name2 val2
2 mypath\is\this\name3 val3
3 mynewpath\is\this\name1 val1
4 mynewpath\is\this\name2 val2
5 mynewpath\is\this\name3 val3