vla*_*gre 65 python dataframe pandas
假设我有一个带结构的嵌套字典'user_dict':
第1级: UserId(长整数)
第2级:类别(字符串)
第3级:各种属性(浮点数,整数等)
例如,这个字典的条目是:
user_dict[12] = {
"Category 1": {"att_1": 1,
"att_2": "whatever"},
"Category 2": {"att_1": 23,
"att_2": "another"}}
Run Code Online (Sandbox Code Playgroud)
"user_dict"中的每个项目具有相同的结构,"user_dict"包含大量项目,我想将这些项目提供给pandas DataFrame,从属性构建系列.在这种情况下,分层索引对于此目的是有用的.
具体来说,我的问题是,是否存在一种方法来帮助DataFrame构造函数理解该系列应该是从字典中"级别3"的值构建的?
如果我尝试类似的东西:
df = pandas.DataFrame(users_summary)
Run Code Online (Sandbox Code Playgroud)
"级别1"(用户ID)中的项目被视为列,这与我想要实现的目标相反(将用户ID作为索引).
我知道我可以在迭代字典条目后构建系列,但如果有更直接的方法,这将非常有用.类似的问题是询问是否可以从文件中列出的json对象构造pandas DataFrame.
Wou*_*ire 102
一个pandas MultiIndex由一个元组列表组成.因此,最自然的方法是重新整形输入dict,使其键是与您需要的多索引值对应的元组.然后,您可以pd.DataFrame.from_dict使用以下选项构建数据框orient='index':
user_dict = {12: {'Category 1': {'att_1': 1, 'att_2': 'whatever'},
'Category 2': {'att_1': 23, 'att_2': 'another'}},
15: {'Category 1': {'att_1': 10, 'att_2': 'foo'},
'Category 2': {'att_1': 30, 'att_2': 'bar'}}}
pd.DataFrame.from_dict({(i,j): user_dict[i][j]
for i in user_dict.keys()
for j in user_dict[i].keys()},
orient='index')
att_1 att_2
12 Category 1 1 whatever
Category 2 23 another
15 Category 1 10 foo
Category 2 30 bar
Run Code Online (Sandbox Code Playgroud)
另一种方法是通过连接组件数据帧来构建数据帧:
user_ids = []
frames = []
for user_id, d in user_dict.iteritems():
user_ids.append(user_id)
frames.append(pd.DataFrame.from_dict(d, orient='index'))
pd.concat(frames, keys=user_ids)
att_1 att_2
12 Category 1 1 whatever
Category 2 23 another
15 Category 1 10 foo
Category 2 30 bar
Run Code Online (Sandbox Code Playgroud)
小智 33
该解决方案应该通过将字典键扁平化为元组链来适用于任意深度
def flatten_dict(nested_dict):
res = {}
if isinstance(nested_dict, dict):
for k in nested_dict:
flattened_dict = flatten_dict(nested_dict[k])
for key, val in flattened_dict.items():
key = list(key)
key.insert(0, k)
res[tuple(key)] = val
else:
res[()] = nested_dict
return res
def nested_dict_to_df(values_dict):
flat_dict = flatten_dict(values_dict)
df = pd.DataFrame.from_dict(flat_dict, orient="index")
df.index = pd.MultiIndex.from_tuples(df.index)
df = df.unstack(level=-1)
df.columns = df.columns.map("{0[1]}".format)
return df
Run Code Online (Sandbox Code Playgroud)
cs9*_*s95 15
pd.concat接受字典。考虑到这一点,可以通过使用字典理解来构建将键映射到子帧的字典,从而在简单性和性能方面改进当前接受的答案。
pd.concat({k: pd.DataFrame(v).T for k, v in user_dict.items()}, axis=0)
Run Code Online (Sandbox Code Playgroud)
要么,
pd.concat({
k: pd.DataFrame.from_dict(v, 'index') for k, v in user_dict.items()
},
axis=0)
Run Code Online (Sandbox Code Playgroud)
att_1 att_2
12 Category 1 1 whatever
Category 2 23 another
15 Category 1 10 foo
Category 2 30 bar
Run Code Online (Sandbox Code Playgroud)
Mis*_*iko 13
所以我曾经使用for循环来迭代字典,但我发现有一件事情更快,就是转换为面板然后转换为数据帧.说你有一本字典d
import pandas as pd
d
{'RAY Index': {datetime.date(2014, 11, 3): {'PX_LAST': 1199.46,
'PX_OPEN': 1200.14},
datetime.date(2014, 11, 4): {'PX_LAST': 1195.323, 'PX_OPEN': 1197.69},
datetime.date(2014, 11, 5): {'PX_LAST': 1200.936, 'PX_OPEN': 1195.32},
datetime.date(2014, 11, 6): {'PX_LAST': 1206.061, 'PX_OPEN': 1200.62}},
'SPX Index': {datetime.date(2014, 11, 3): {'PX_LAST': 2017.81,
'PX_OPEN': 2018.21},
datetime.date(2014, 11, 4): {'PX_LAST': 2012.1, 'PX_OPEN': 2015.81},
datetime.date(2014, 11, 5): {'PX_LAST': 2023.57, 'PX_OPEN': 2015.29},
datetime.date(2014, 11, 6): {'PX_LAST': 2031.21, 'PX_OPEN': 2023.33}}}
Run Code Online (Sandbox Code Playgroud)
命令
pd.Panel(d)
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 4 (minor_axis)
Items axis: RAY Index to SPX Index
Major_axis axis: PX_LAST to PX_OPEN
Minor_axis axis: 2014-11-03 to 2014-11-06
Run Code Online (Sandbox Code Playgroud)
其中pd.Panel(d)[item]产生一个数据帧
pd.Panel(d)['SPX Index']
2014-11-03 2014-11-04 2014-11-05 2014-11-06
PX_LAST 2017.81 2012.10 2023.57 2031.21
PX_OPEN 2018.21 2015.81 2015.29 2023.33
Run Code Online (Sandbox Code Playgroud)
然后,您可以点击命令to_frame()将其转换为数据帧.我也使用reset_index将主轴和次轴转换为列而不是将它们作为索引.
pd.Panel(d).to_frame().reset_index()
major minor RAY Index SPX Index
PX_LAST 2014-11-03 1199.460 2017.81
PX_LAST 2014-11-04 1195.323 2012.10
PX_LAST 2014-11-05 1200.936 2023.57
PX_LAST 2014-11-06 1206.061 2031.21
PX_OPEN 2014-11-03 1200.140 2018.21
PX_OPEN 2014-11-04 1197.690 2015.81
PX_OPEN 2014-11-05 1195.320 2015.29
PX_OPEN 2014-11-06 1200.620 2023.33
Run Code Online (Sandbox Code Playgroud)
最后,如果你不喜欢的方式框架看起来你可以用面板的转置函数调用to_frame前更改外观()见文档这里 http://pandas.pydata.org/pandas-docs/dev/generated /pandas.Panel.transpose.html
仅作为一个例子
pd.Panel(d).transpose(2,0,1).to_frame().reset_index()
major minor 2014-11-03 2014-11-04 2014-11-05 2014-11-06
RAY Index PX_LAST 1199.46 1195.323 1200.936 1206.061
RAY Index PX_OPEN 1200.14 1197.690 1195.320 1200.620
SPX Index PX_LAST 2017.81 2012.100 2023.570 2031.210
SPX Index PX_OPEN 2018.21 2015.810 2015.290 2023.330
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
如果有人想要在没有多索引的情况下以“长格式”(叶值具有相同类型)获取数据框,您可以这样做:
pd.DataFrame.from_records(
[
(level1, level2, level3, leaf)
for level1, level2_dict in user_dict.items()
for level2, level3_dict in level2_dict.items()
for level3, leaf in level3_dict.items()
],
columns=['UserId', 'Category', 'Attribute', 'value']
)
UserId Category Attribute value
0 12 Category 1 att_1 1
1 12 Category 1 att_2 whatever
2 12 Category 2 att_1 23
3 12 Category 2 att_2 another
4 15 Category 1 att_1 10
5 15 Category 1 att_2 foo
6 15 Category 2 att_1 30
7 15 Category 2 att_2 bar
Run Code Online (Sandbox Code Playgroud)
(我知道最初的问题可能希望 (I.) 将级别 1 和 2 作为多索引,将级别 3 作为列,并且 (II.) 询问除 dict 中的值迭代之外的其他方式。但我希望这个答案仍然相关和有用的(I.):对于像我这样试图找到一种方法将嵌套的字典变成这种形状的人,谷歌只返回这个问题和(II。):因为其他答案也涉及一些迭代,我发现这个方法灵活且易于阅读;但不确定性能。)
对于表示数据的其他方式,您不需要做太多事情。例如,如果您只希望“外部”键是索引,“内部”键是列,值是单元格值,则可以这样做:
df = pd.DataFrame.from_dict(user_dict, orient='index')
Run Code Online (Sandbox Code Playgroud)
基于经过验证的答案,对我来说这效果最好:
ab = pd.concat({k: pd.DataFrame(v).T for k, v in data.items()}, axis=0)
ab.T
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
71913 次 |
| 最近记录: |