我有一个csv,其中包含多个填充了单个dict的列。有数千行。我想把这些dicts拉出来并从他们的键中创建列,并用他们的值填充单元格,填充缺少值的NaN。那样:
id attributes
0 255RSSSTCHL-QLTDGLZD-BLK {"color": "Black", "hardware": "Goldtone"}
1 C3ACCRDNFLP-QLTDS-S-BLK {"size": "Small", "color": "Black"}
变为:
id size color hardware
0 255RSSSTCHL-QLTDGLZD-BLK NaN Black Goldtone
1 C3ACCRDNFLP-QLTDS-S-BLK Small Black NaN
有几个像'id'这样的列,我想在结果DataFrame中保持不变,并且有几个列像'attributes',这些列填充了我要吹成列的dicts。我将它们截断到上面的示例中进行说明。
答案 0 :(得分:2)
来源DF:
In [172]: df
Out[172]:
id attributes attr2
0 255RSSSTCHL-QLTDGLZD-BLK {"color":"Black","hardware":"Goldtone"} {"aaa":"aaa", "bbb":"bbb"}
1 C3ACCRDNFLP-QLTDS-S-BLK {"size":"Small","color":"Black"} {"ccc":"ccc"}
解决方案1:
import ast
attr_cols = ['attributes','attr2']
def f(df, attr_col):
return df.join(df.pop(attr_col) \
.apply(lambda x: pd.Series(ast.literal_eval(x))))
for col in attr_cols:
df = f(df, col)
解决方案2:感谢@DYZ for the hint:
import json
attr_cols = ['attributes','attr2']
def f(df, attr_col):
return df.join(df.pop(attr_col) \
.apply(lambda x: pd.Series(json.loads(x))))
for col in attr_cols:
df = f(df, col)
<强>结果:强>
In [175]: df
Out[175]:
id color hardware size aaa bbb ccc
0 255RSSSTCHL-QLTDGLZD-BLK Black Goldtone NaN aaa bbb NaN
1 C3ACCRDNFLP-QLTDS-S-BLK Black NaN Small NaN NaN ccc
时间:为20.000行DF:
In [198]: df = pd.concat([df] * 10**4, ignore_index=True)
In [199]: df.shape
Out[199]: (20000, 3)
In [201]: %paste
def f_ast(df, attr_col):
return df.join(df.pop(attr_col) \
.apply(lambda x: pd.Series(ast.literal_eval(x))))
def f_json(df, attr_col):
return df.join(df.pop(attr_col) \
.apply(lambda x: pd.Series(json.loads(x))))
## -- End pasted text --
In [202]: %%timeit
...: for col in attr_cols:
...: f_ast(df.copy(), col)
...:
1 loop, best of 3: 33.1 s per loop
In [203]:
In [203]: %%timeit
...: for col in attr_cols:
...: f_json(df.copy(), col)
...:
1 loop, best of 3: 30 s per loop
In [204]: df.shape
Out[204]: (20000, 3)
答案 1 :(得分:0)
您可以使用pd.read_csv
选项在converters
调用中嵌入字符串解析
import pandas as pd
from io import StringIO
from cytoolz.dicttoolz import merge as dmerge
from json import loads
txt = """id|attributes|attr2
255RSSSTCHL-QLTDGLZD-BLK|{"color":"Black","hardware":"Goldtone"}|{"aaa":"aaa", "bbb":"bbb"}
C3ACCRDNFLP-QLTDS-S-BLK|{"size":"Small","color":"Black"}|{"ccc":"ccc"}"""
converters = dict(attributes=loads, attr2=loads)
df = pd.read_csv(StringIO(txt), sep='|', index_col='id', converters=converters)
df
然后我们可以merge
每行的字典并转换为pd.DataFrame
。我将cytoolz.dicttoolz.merge
导入为dmerge
以上。
pd.DataFrame(df.apply(dmerge, 1).values.tolist(), df.index).reset_index()
id aaa bbb ccc color hardware size
0 255RSSSTCHL-QLTDGLZD-BLK aaa bbb NaN Black Goldtone NaN
1 C3ACCRDNFLP-QLTDS-S-BLK NaN NaN ccc Black NaN Small