为了账号安全,请及时绑定邮箱和手机立即绑定

如何在Python中从字典中获取对称矩阵

如何在Python中从字典中获取对称矩阵

牧羊人nacy 2023-07-05 17:59:18
我有一个关于 Python 中数据操作的基本问题。我有以下字典:mydict={('A', 'E'): 23972, ('A', 'D'): 10730, ('A', 'B'): 14748, ('A', 'C'): 3424, ('E', 'D'): 3294, ('E', 'B'): 16016, ('E', 'C'): 3373, ('D', 'B'): 69734, ('D', 'C'): 4662, ('B', 'C'): 159161}如果仔细观察,这是一个对角线为零的对称矩阵的一半(不包括 0)。我的最终目标是编写一个具有完整矩阵的 pandas 数据框。暂定方案我考虑过“解压”字典,获取 5 个列表,每个标签一个,所有值都与其他标签相关,在列表的自身位置添加 0。对于标签“A”和“B”,所需的结果是:A=[0,mydict(['A','B']),mydict(['A','C']),mydict(['A','D']),mydict(['A','E'])]B=[mydict(['A','B']),0,mydict(['B','C']),mydict(['D','B']),mydict(['E','B'])]C、D、E 依此类推。请注意,在 B 中,第 4 个和第 5 个元素是 mydict(['D','B']) 和 mydict(['E','B']),因为 mydict(['B','D']) mydict(['B','E']) 根本不存在于 mydict 中。这样我就可以轻松地从这些列表中填充数据框:import pandas as pddf=pd.DataFrame(columns=['A','B','C','D','E'])df['A']=Adf['B']=B问题我不太确定如何将 mydict“解压”到这些列表中,或解压到任何其他可以帮助我构建矩阵的容器中。有什么建议么?
查看完整描述

4 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

一种选择是以完整矩阵格式重建字典,然后用 pandas 对其进行旋转:


import pandas as pd

mydict={('A', 'E'): 23972,

 ('A', 'D'): 10730,

 ('A', 'B'): 14748,

 ('A', 'C'): 3424,

 ('E', 'D'): 3294,

 ('E', 'B'): 16016,

 ('E', 'C'): 3373,

 ('D', 'B'): 69734,

 ('D', 'C'): 4662,

 ('B', 'C'): 159161}

 

 

# construct the full dictionary

newdict = {}


for (k1, k2), v in mydict.items():

    newdict[k1, k2] = v

    newdict[k2, k1] = v

    newdict[k1, k1] = 0

    newdict[k2, k2] = 0


# pivot the result from long to wide

pd.Series(newdict).reset_index().pivot(index='level_0', columns='level_1', values=0)


#level_1      A       B       C      D      E

#level_0                                     

#A            0   14748    3424  10730  23972

#B        14748       0  159161  69734  16016

#C         3424  159161       0   4662   3373

#D        10730   69734    4662      0   3294

#E        23972   16016    3373   3294      0


查看完整回答
反对 回复 2023-07-05
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

这是一个直接的解决方案,运行起来也不应该花费太多时间 -


cols = np.unique(list(mydict.keys())).ravel()


df = pd.DataFrame(0, columns=cols, index=cols)


for i in mydict.items():

    df.loc[i[0]] = i[1] 


df = df + df.T

print(df)

       A       B       C      D      E

A      0   14748    3424  10730  23972

B  14748       0  159161  69734  16016

C   3424  159161       0   4662   3373

D  10730   69734    4662      0   3294

E  23972   16016    3373   3294      0

基准测试


添加基准(303长度输入,MacBook pro 13)-


kk = 'ABCDEFGHIJKLMNOPQURSUVWXYZ'

mydict = {i:np.random.randint(1,10000) for i in itertools.combinations(kk,2)}

len(mydict)

#303

  • fusion 的方法- 每个循环 392 µs ± 16.4 µs(7 次运行的平均值 ± 标准差,每次 1000 个循环)

  • Psidom 的方法- 每个循环 4.95 ms ± 286 µs(7 次运行的平均值 ± 标准差,每次 100 个循环)

  • Akshay Sehgal 的方法- 每个循环 34.8 ms ± 884 µs(7 次运行的平均值 ± 标准差,每次 10 个循环)

  • Ben.T 的方法- 每个循环 4.01 ms ± 282 µs(7 次运行的平均值 ± 标准差,每次 100 个循环)

Fusion 的方法是最快的。


查看完整回答
反对 回复 2023-07-05
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

我能想到的是首先将字典值填充到数组中,然后构造数据框。


mydict={('A', 'E'): 23972,

 ('A', 'D'): 10730,

 ('A', 'B'): 14748,

 ('A', 'C'): 3424,

 ('E', 'D'): 3294,

 ('E', 'B'): 16016,

 ('E', 'C'): 3373,

 ('D', 'B'): 69734,

 ('D', 'C'): 4662,

 ('B', 'C'): 159161}

 

import numpy as np

import pandas as pd


a = np.full((5,5),0)

ss = 'ABCDE'


for k, i in mydict.items():

    f,s = k 

    fi = ss.index(f)

    si = ss.index(s)

    a[fi,si] = i

    a[si,fi] = i


# if you want to keep the diagonal

df = pd.DataFrame(a)


# if you want to remove diagonal:

no_diag = np.delete(a,range(0,a.shape[0]**2,(a.shape[0]+1))).reshape(a.shape[0],(a.shape[1]-1))


df = pd.DataFrame(no_diag)


查看完整回答
反对 回复 2023-07-05
?
SMILET

TA贡献1796条经验 获得超4个赞

一旦从字典中创建一个系列,然后unstack获取一个数据帧。获取union索引和列,以便能够reindex同时获取所有可能的值。将此数据帧的转置添加到自身以查找缺失值。


df_ = pd.Series(mydict).unstack(fill_value=0)

idx = df_.index.union(df_.columns)

df_ = df_.reindex(index=idx, columns=idx, fill_value=0)

df_ += df_.T


print(df_)

       A       B       C      D      E

A      0   14748    3424  10730  23972

B  14748       0  159161  69734  16016

C   3424  159161       0   4662   3373

D  10730   69734    4662      0   3294

E  23972   16016    3373   3294      0


查看完整回答
反对 回复 2023-07-05
  • 4 回答
  • 0 关注
  • 147 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信