繁体   English   中英

试图从 python 字典创建一个二维数组

[英]Trying to create a 2D array from python dictionary

我正在尝试从 python 中的字典创建一个二维数组。

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

我想要一个显示匹配项数的二维数组。(即比较键和它们的值并将匹配的值存储在二维数组中)

Output Format:

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

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

获得结果的一种不错的方法是使用熊猫 (Numpy的大哥):

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

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

那么矩阵是完全对称的,因此您只需要计算(a,b)的值(a,b)而不是两个(a,b), (b,a)

除此之外,您可以计算每对交叉点的交点大小:

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

您可以随意创建列表,但是先形成集合比重复创建集合要快:

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]]

此处提供的其他解决方案适用于较小的输入列表,但是随着列表的增加,它们将随着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()将其转换为密集数组形式; 使用熊猫,您还可以将标签应用于行和列:

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

此处的稀疏方法要快两个数量级。

当然,这不是执行该任务的最优雅的方法,但它确实有效

import numpy as np
N = len(mydictionary)
freqs = np.zeros(shape=(N, N), dtype=np.int)
mykeys = sorted(mydictionary.keys())
for i, x in enumerate(mykeys):
    freqs[i, i] = len(mydictionary[x])
    for j in range(i+1, N):
        for elem in mydictionary[x]:
            if elem in mydictionary[mykeys[j]]:
                freqs[i, j] += 1
                freqs[j, i] += 1
print freqs
#[[3 1 1]
# [1 2 0]
# [1 0 1]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM