试图从python字典创建一个2D数组

时间:2016-04-25 19:38:32

标签: python arrays numpy

我正在尝试用python中的字典创建一个2D数组。

mydictionary={
'a':['review','read','study'],
'b':['read'],
'c':['review','dictate']}

我希望有一个2D数组,显示匹配项目的数量。(即比较键及其值并将匹配值存储在2D数组中)

Output Format:

       a       b       c
  ___|___________________
  a  |  3       1       1
     |
  b  |  1       1       0
     |
  c  |  1       0       2

我的词典有大约7000个项目。实现这一目标的最佳方法是什么? 感谢

5 个答案:

答案 0 :(得分:1)

获得结果的一种甜蜜方式是使用pandas,这个笨拙的大哥:

In [6]: md=mydictionary
In [7]: df=pd.DataFrame([[len(set(md[i])&set(md[j])) for j in md] for i in md],md,md)
In [8]: df
Out[8]: 
   c  a  b
c  2  1  0
a  1  3  1
b  0  1  1

如果订单重要:

In [9]: df.sort_index(0).sort_index(1)
Out[9]: 
   a  b  c
a  3  1  1
b  1  1  0
c  1  0  2

答案 1 :(得分:0)

对于初学者,您可以使用对角线只是各个列表长度的事实。

然后矩阵是完全对称的,因此您只需计算(a,b)的值而不是(a,b), (b,a)

的值

过去,您可以计算每对的交叉点大小:

len([filter(lambda x: x in arr1, subArr) for subArr in arr2])

答案 2 :(得分:0)

您可以根据需要形成列表,但首先形成集合将比重复创建集合更快:

new = {k: set(v) for k, v in mydictionary.items()}
out = OrderedDict()
for k, v in new.items():
    out[k] = [k, len(v)]
    for k2, v2 in new.items():
        if k2 == k:
            continue
        out[k].append(sum(val in v for val in v2))


print(list(out.values()))

输出:

[['a', 3, 1, 1], ['c', 2, 1, 0], ['b', 1, 1, 0]]

答案 3 :(得分:0)

此处提供的其他解决方案适用于较小的输入列表,但随着列表的增长,它们将扩展为O[N^2](充其量),在您的情况下可能相对较慢。这是一种使用scikit-learn DictVectorizer的方法,对于具有少量重叠的大输入应该更快。

我们的想法是构建输入的单热编码,然后使用矩阵乘积来计算最终结果:

from sklearn.feature_extraction import DictVectorizer

keys, vals = zip(*mydictionary.items())
valsdict = [dict(zip(val, repeat(1))) for val in vals]

V = DictVectorizer().fit_transform(valsdict)
result = V.dot(V.T)

结果将是scipy.sparse矩阵,它只显式存储非零元素。您可以使用result.toarray()将其转换为密集数组形式;使用pandas,您还可以将标签应用于行和列:

import pandas as pd
pd.DataFrame(result.toarray(), keys, keys)
#    a  c  b
# a  3  1  1
# c  1  2  0
# b  1  0  1

我希望随着输入大小的增加,这将比其他解决方案更快显着

编辑:这是1000项输入的基准,其中大约一半的对有一些重叠:

import numpy as np
import pandas as pd
from itertools import repeat
from sklearn.feature_extraction import DictVectorizer

def dense_method(md):
    return pd.DataFrame([[len(set(md[i]) & set(md[j]))
                          for j in md]
                         for i in md], md, md)

def sparse_method(mydictionary):
    keys, vals = zip(*mydictionary.items())
    valsdict = [dict(zip(val, repeat(1))) for val in vals]
    V = DictVectorizer().fit_transform(valsdict)
    return pd.DataFrame(V.dot(V.T).toarray(), keys, keys)


mydictionary = {i: np.random.randint(0, 20, 3)
                for i in range(1000)}

print(np.allclose(dense_method(mydictionary),
                  sparse_method(mydictionary)))
# True

%timeit sparse_method(mydictionary)
# 100 loops, best of 3: 19.5 ms per loop

%timeit dense_method(mydictionary)
# 1 loops, best of 3: 3.41 s per loop

稀疏方法在这里快了两个数量级。

答案 4 :(得分:-1)

当然不是执行该任务的最优雅方式,但它可以正常工作

 Blog.php