我正在尝试用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个项目。实现这一目标的最佳方法是什么? 感谢
答案 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