如何在python中将子字典有效地转换为矩阵

时间:2018-11-25 03:46:30

标签: python arrays numpy dictionary matrix

我有一本这样的字典:

{'test2':{'hi':4,'bye':3}, 'religion.christian_20674': {'path': 1, 'religious': 1, 'hi':1}}

此字典的值本身就是字典。

我的输出应如下所示:

enter image description here

我如何有效地做到这一点?

我已读过this帖子,其中矩阵的形状与我的不同。

this一个与我的情况最接近,但是它在字典中有一个集合,而不是另一个字典。

问题不同的是,我还希望将内部字典的值转换为矩阵的值。

我在想这样的事情:

doc_final =[[]]
for item in dic1:
    for item2, value in dic1[item]:
        doc_final[item][item2] = value

但这不是正确的方法。

感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

使用熊猫库,您可以轻松地将字典变成矩阵。

代码:

import pandas as pd

d = {'test2':{'hi':4,'bye':3}, 'religion.christian_20674': {'path': 1, 'religious': 1, 'hi':1}}
df = pd.DataFrame(d).T.fillna(0)

print(df)

输出:

                          bye   hi  path  religious
test2                     3.0  4.0   0.0        0.0
religion.christian_20674  0.0  1.0   1.0        1.0

答案 1 :(得分:1)

在Pandas或Numpy中似乎没有任何内置的方式可以根据需要拆分行。幸运的是,您可以通过单个词典理解来做到这一点。下面显示的splitsubdicts函数可提供dict理解,而todf函数则涵盖了整个转换过程:

def splitsubdicts(d):
    return {('%s_%d' % (k0, i + 1)):{k1:v1} for k0,v0 in d.items() for i,(k1,v1) in enumerate(v0.items())}

def todf(d):
    # .fillna(0) replaces the missing data with 0 (by default NaN is assigned to missing data)
    return pd.DataFrame(splitsubdicts(splitsubdicts(d))).T.fillna(0)

您可以像这样使用todf

d = {'Test2': {'hi':4, 'bye':3}, 'religion.christian_20674': {'path': 1, 'religious': 1, 'hi':1}}
df = todf(d)
print(df)

输出:

                              bye   hi  path  religious
Test2_1_1                     0.0  4.0   0.0        0.0
Test2_2_1                     3.0  0.0   0.0        0.0
religion.christian_20674_1_1  0.0  0.0   1.0        0.0
religion.christian_20674_2_1  0.0  0.0   0.0        1.0
religion.christian_20674_3_1  0.0  1.0   0.0        0.0

如果您实际上想要一个Numpy数组,则可以轻松地转换数据框:

arr = df.values
print(arr)

输出:

[[0. 4. 0. 0.]
 [3. 0. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]
 [0. 1. 0. 0.]]

您还可以改为将数据框转换为structured array,这样就可以保留行和列标签:

arr = df.to_records()
print(arr.dtype.names)
print(arr)

输出:

('index', 'bye', 'hi', 'path', 'religious')
[('Test2_1_1', 0., 4., 0., 0.)
 ('Test2_2_1', 3., 0., 0., 0.)
 ('religion.christian_20674_1_1', 0., 0., 1., 0.)
 ('religion.christian_20674_2_1', 0., 0., 0., 1.)
 ('religion.christian_20674_3_1', 0., 1., 0., 0.)]

编辑:splitsubdicts

的说明

splitsubdicts中使用的嵌套字典理解似乎有点令人困惑。确实,这只是编写嵌套循环的简写。您可以这样在两个for循环中扩展理解力:

def splitsubdicts(d):
    ret = {}

    for k0,v0 in d.items():
        for i,(k1,v1) in enumerate(v0.items()):
            ret['{}_{}'.format(k0, i + 1)] = {k1: v1}

    return ret

此基于循环的splitsubdicts返回的值将与上述基于理解的版本返回的值相同。基于理解的版本might be slightly faster比基于循环的版本instructions更好,但实际上,这不是任何人都应该担心的事情。