我有一本这样的字典:
{'test2':{'hi':4,'bye':3}, 'religion.christian_20674': {'path': 1, 'religious': 1, 'hi':1}}
此字典的值本身就是字典。
我的输出应如下所示:
我如何有效地做到这一点?
我已读过this帖子,其中矩阵的形状与我的不同。
this一个与我的情况最接近,但是它在字典中有一个集合,而不是另一个字典。
问题不同的是,我还希望将内部字典的值转换为矩阵的值。
我在想这样的事情:
doc_final =[[]]
for item in dic1:
for item2, value in dic1[item]:
doc_final[item][item2] = value
但这不是正确的方法。
感谢您的帮助:)
答案 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更好,但实际上,这不是任何人都应该担心的事情。