pandas 嵌套字典-->重组字典-->多索引 Dataframe -->堆叠,结果不是所需的,因为值被分隔

e0bqpujr  于 2022-11-20  发布在  其他
关注(0)|答案(2)|浏览(127)

我 有 一 个 嵌套 的 字典 , 看 起来 像 这样 :

test_dict = {'header1_1': {'header2_1': {'header3_1': {'header4_1': ['322.5', 330.0, -0.28],
    'header4_2': ['322.5', 332.5, -0.26]},
   'header3_2': {'header4_1': ['285.0', 277.5, -0.09],
    'header4_2': ['287.5', 277.5, -0.12]}},
  'header2_2': {'header3_1': {'header4_1': ['345.0', 357.5, -0.14],
    'header4_2': ['345.0', 362.5, -0.14]},
   'header3_2': {'header4_1': ['257.5', 245.0, -0.1],
    'header4_2': ['257.5', 240.0, -0.08]}}}}

中 的 每 一 个
标 头 有 4 个 级别 , 每个 级别 可以 有 多 个 值 , 例如 header1_1 、 header1_2 。 指定 这些 标 头 的 组合 后 , 您 将 拥有 一 个 包含 3 个 值 的 列表 。
我 想 把 它 放到 一 个 数据 帧 中 , 所以 我 创建 了 一 个 经过 修改 的 字典 :

reformed_dict = {}
for outerKey, innerDict in test_dict.items():
    for innerKey, innerDict2 in innerDict.items():
        for innerKey2, innerDict3 in innerDict2.items():
            for innerKey3, values in innerDict3.items():
                reformed_dict[(outerKey,
                        innerKey, innerKey2, innerKey3)] = values
  
reformed_dict

格式
修改 后 的 词典 如下 :
{( " 标题 1_1 " 、 " 标题 2_1 " 、 " 标题 3_1 " 、 " 标题 4_1 " ) :[ " 322.5 " , 330.0 , -0.28 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_1 ' 、 ' 信 头 3_1 ' 、 ' 信 头 4_2 ' ) :[ " 322.5 " , 332.5 , -0.26 ] ,
( " 标题 1_1 " 、 " 标题 2_1 " 、 " 标题 3_2 " 、 " 标题 4_1 " ) :[ " 285.0 " , 277.5 , -0.09 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_1 ' 、 ' 信 头 3_2 ' 、 ' 信 头 4_2') :[ " 287.5 " , 277.5 , -0.12 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_2 ' 、 ' 信 头 3_1 ' 、 ' 信 头 4_1 ' ) :[ " 345.0 " , 357.5 , -0.14 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_2 ' 、 ' 信 头 3_1 ' 、 ' 信 头 4_2 ' ) :[ " 345.0 " , 362.5 , -0.14 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_2 ' 、 ' 信 头 3_2 ' 、 ' 信 头 4_1 ' ) :[ " 257.5 " , 245.0 , -0.1 ] ,
( ' 信 头 1_1 ' 、 ' 信 头 2_2 ' 、 ' 信 头 3_2 ' 、 ' 信 头 4_2') :【 257.5 , 240.0 , -0.08 】
将 其 放入 数据 帧 :

df = pandas.DataFrame(reformed_dict)

格式
它 看 起来 像 :
报头 1_1
报头 2_1 报头 2_2
报头 3_1 报头 3_2 报头 3_1 报头 3_2
头 4_1 头 4_2 头 4_1 头 4_2 头 4_1 头 4_2 头 4_1 头 4_2 头 4_1 头 4_2
2000 年 12 月 31 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 2000 年 6 月 30 日 终 了 的 200
2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 2000 年 12 月 31 日 终 了 的 200
一 个 月 后 , 该 指数 将 下降 。
我 想 做 的 是 让 所有 的 列 标题 都 是 行 标题 , 每个 标题 组合 有 3 列 , 我 将 这些 列 命名 为 Val1 、 Val2 、 Val3 。
因此 我 使用 df . stack ( ) 将 列 标题 推入 行 中 :

df_1 = df.stack(level=0)
df_2 = df_1.stack(level=0)
df_3 = df_2.stack(level=0)
df_4 = df_3.stack(level=0)
print(df_4)

格式
其 结果 是 :
报头 1_1 报头 2_1 报头 3_1 报头 4_1 322.5
报头 4_2 322.5
报头 3_2 报头 4_1 285.0
标题 4_2 287.5
报头 2_2 报头 3_1 报头 4_1 345.0
报头 4_2 345.0
报头 3_2 报头 4_1 257.5
标题 4_2 257.5
1 报头 1_1 报头 2_1 报头 3_1 报头 4_1 330.0
报头 4_2 332.5
报头 3_2 报头 4_1 277.5
标题 4_2 277.5
报头 2_2 报头 3_1 报头 4_1 357.5
报头 4_2 362.5
报头 3_2 报头 4_1 245.0
报头 4_2 240.0
2 个 报头 1_1 个 报头 2_1 个 报头 3_1 个 报头 4_1 -0.28
报头 4_2 -0.26
报头 3_2 报头 4_1 -0.09
报头 4_2 -0.12
报头 2_2 报头 3_1 报头 4_1 -0.14
报头 4_2 -0.14
报头 3_2 报头 4_1 -0.1
报头 4_2 -0.08
这 不是 我 想要 的 布局 , 因为 我 希望 每个 列表 中 的 3 个 值 都 在 同一 行 上 , 就 像 它们 在 经过 修改 的 字典 中 的 情况 一样 。
我 如何 才能 做到 这 一 点 ?

ve7v8dk2

ve7v8dk21#

您正在查找的是MultiIndex
将dict的键转换为索引并将dict值用作数据:

keys = reformed_dict.keys()
index = pd.MultiIndex.from_tuples(keys, names=["header1", "header2", "header3", "header4"])

values = [reformed_dict[k] for k in keys]

df = pd.DataFrame(data=values, index=index)

输出量:

header1   header2   header3   header4                      
header1_1 header2_1 header3_1 header4_1  322.5  330.0 -0.28
                              header4_2  322.5  332.5 -0.26
                    header3_2 header4_1  285.0  277.5 -0.09
                              header4_2  287.5  277.5 -0.12
          header2_2 header3_1 header4_1  345.0  357.5 -0.14
                              header4_2  345.0  362.5 -0.14
                    header3_2 header4_1  257.5  245.0 -0.10
                              header4_2  257.5  240.0 -0.08

如果希望索引为列:

df = df.reset_index()

输出量:

header1    header2    header3    header4      0      1     2
0  header1_1  header2_1  header3_1  header4_1  322.5  330.0 -0.28
1  header1_1  header2_1  header3_1  header4_2  322.5  332.5 -0.26
2  header1_1  header2_1  header3_2  header4_1  285.0  277.5 -0.09
3  header1_1  header2_1  header3_2  header4_2  287.5  277.5 -0.12
4  header1_1  header2_2  header3_1  header4_1  345.0  357.5 -0.14
5  header1_1  header2_2  header3_1  header4_2  345.0  362.5 -0.14
6  header1_1  header2_2  header3_2  header4_1  257.5  245.0 -0.10
7  header1_1  header2_2  header3_2  header4_2  257.5  240.0 -0.08
cedebl8k

cedebl8k2#

请尝试:

test_dict = \
{'header1_1': {'header2_1': {'header3_1': {'header4_1': ['322.5', 330.0, -0.28],
                                           'header4_2': ['322.5', 332.5, -0.26]},
                             'header3_2': {'header4_1': ['285.0', 277.5, -0.09],
                                           'header4_2': ['287.5', 277.5, -0.12]}},
               'header2_2': {'header3_1': {'header4_1': ['345.0', 357.5, -0.14],
                                           'header4_2': ['345.0', 362.5, -0.14]},
                             'header3_2': {'header4_1': ['257.5', 245.0, -0.10],
                                           'header4_2': ['257.5', 240.0, -0.08]}}}}
#from pprint import pprint
#pprint(test_dict)

from collections import defaultdict
import pandas as pd
dct_N = defaultdict(list)
total_rows = 0
def fillDataFrameDict(dct, level=0):
    global dct_N, total_rows
    for key, value in dct.items():
        if not isinstance(value, dict):
            dct_N[f'headerNo_{level+1}'].append(key)
            total_rows += 1 
            dct_N['body'].append(value)
            for key_N, value_N in dct_N.items():
                dct_N[key_N] = value_N + (total_rows-len(value_N))*[value_N[-1]]
        else: 
            dct_N[f'headerNo_{level+1}'].append(key)
            fillDataFrameDict(value, level+1)

fillDataFrameDict(test_dict)
df = pd.DataFrame(dct_N)
print(df)

其给出:

headerNo_1 headerNo_2 headerNo_3 headerNo_4                   body
0  header1_1  header2_1  header3_1  header4_1  [322.5, 330.0, -0.28]
1  header1_1  header2_1  header3_1  header4_2  [322.5, 332.5, -0.26]
2  header1_1  header2_1  header3_2  header4_1  [285.0, 277.5, -0.09]
3  header1_1  header2_1  header3_2  header4_2  [287.5, 277.5, -0.12]
4  header1_1  header2_2  header3_1  header4_1  [345.0, 357.5, -0.14]
5  header1_1  header2_2  header3_1  header4_2  [345.0, 362.5, -0.14]
6  header1_1  header2_2  header3_2  header4_1   [257.5, 245.0, -0.1]
7  header1_1  header2_2  header3_2  header4_2  [257.5, 240.0, -0.08]

当处理深度嵌套列表或字典时,使用递归遍历嵌套分支是一个很好的例子,在这里使用递归是有意义的。
沿着body元素的路径,上面的递归函数测试字典值的类型,并在该值不是字典时停止递归调用。
通过在递归调用期间跟踪行的级别和数量,可以使用适当的值填充列,因此在创建PandasDataFrame时,每列中的行元素数量相等。
collections模块中提供的defaultdict(list) dictionary对象(标准Python安装的一部分)创建一个空列表作为值,并为尚未存储在字典中的键返回该值。这节省了在用项填充列表之前在字典中创建第一个key:value条目所需的一些代码行。

相关问题