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

问题描述

我有一个关于Python中数据处理的基本问题。

我有以下字典:

mydict={('A','E'): 23972,('A','D'): 10730,'B'): 14748,'C'): 3424,('E','D'): 3294,'B'): 16016,'C'): 3373,('D','B'): 69734,'C'): 4662,('B','C'): 159161}

如果仔细看,这是对角线为零的对称矩阵的一半(不包括0)。我的最终目标是编写一个具有完整矩阵的熊猫数据框。

临时解决方案

我考虑过“解包”字典以获得5个列表,每个标签一个,所有值与其他标签相关,在列表的自身位置添加一个0。对于标签“ A”和“ B”,所需结果将是:

A=[0,mydict(['A','B']),'C']),'D']),'E'])]
B=[mydict(['A',mydict(['B',mydict(['D',mydict(['E','B'])]

,以此类推。请注意,在B中,第4个和第5个元素是mydict(['D','B'])和mydict(['E','B']),因为mydict(['B','D'])和mydict(['B','E'])根本就不存在于mydict中。

这样,我可以轻松地从这些列表中填充数据框:

import pandas as pd
df=pd.DataFrame(columns=['A','B','C','D','E'])
df['A']=A
df['B']=B

问题

我不太确定如何将mydict“解包”到那些列表中,或其他可以帮助我构建矩阵的容器中。有什么建议吗?

解决方法

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

import pandas as pd
mydict={('A','E'): 23972,('A','D'): 10730,'B'): 14748,'C'): 3424,('E','D'): 3294,'B'): 16016,'C'): 3373,('D','B'): 69734,'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

或者如@ Ch3steR所评论的那样,您也可以只对枢轴执行pd.Series(newdict).unstack()

Demo link

,

我能想到的是先将dict值填充到一个数组中,然后构造数据帧。

mydict={('A','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)
,

这是一个直接的解决方案,它不需要花费太多时间就可以运行-

const signupForm = document.querySelector('#sign-up-form');
signupForm.addEventListener('submit',(e) => {
    e.preventDefault();

    //get user info
    const username = signupForm['signup-username'].value;
    const email = signupForm['signup-email'].value;
    const password = signupForm['signup-password'].value;

    //signup the user
    auth.createUserWithEmailAndPassword(email,password).then(cred => {
        //createUser function returns the user credentials
        user = auth.currentUser;
    }).then(function () {
        user.updateProfile({
            displayName: username
        })
    }).catch((error) => {
        //Handle errors
        var errorCode = error.code;
        var errorMessage = error.message;
        // [START_EXCLUDE]
        if (errorCode == 'auth/weak-password') {
            alert('The password is too weak.');
        } else {
            alert(errorMessage);
        }
    });
})
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)

基准

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

       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
  • 融合的方法-每个循环392 µs±16.4 µs(平均值±标准偏差,共运行7次,每个循环1000次)
  • Psidom的方法-每个循环4.95毫秒±286微秒(平均±标准偏差,共运行7次,每个循环100次)
  • Akshay Sehgal的方法-每个循环34.8 ms±884 µs(平均±标准偏差,共运行7次,每个循环10个循环)
  • Ben.T的方法-每个循环4.01 ms±282 µs(平均±标准偏差,共运行7次,每个循环100个循环)

从长远来看,融合的方法是最快的。

,

一旦从字典创建一个序列,然后<v-autocomplete :items="hostproperties" :filter="filter" label="Search Host Properties" prepend-icon="mdi-tune" item-text="propertyvalue" item-value="host_id" @change="showHost" > <template slot="selection" slot-scope="data"> {{ data.item.hostpropertytype.name }} - {{ data.item.propertyvalue }} - {{ data.item.hostpropertytype.unit }} </template> <template slot="item" slot-scope="data"> {{ data.item.hostpropertytype.name }} - {{ data.item.propertyvalue }} - {{ data.item.hostpropertytype.unit }} </template> </v-autocomplete> 来获得一个数据框。获取索引和列的showHost() {...},filter(item,queryText,itemText) { const searchText = queryText.toLowerCase(); // define your custom logic of your filter const name = item.hostpropertytype.name.toLowerCase(); const value = item.propertyvalue.toString(); const unit = item.hostpropertytype.unit.toString(); return ( name.indexOf(searchText) > -1 || value.indexOf(searchText) > -1 || unit.indexOf(searchText) > -1 ); } ,使其能够unstack都具有所有可能的值。将此数据框的转置添加到其自身以获取缺少的值。

union

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...