如何将 CSV 数据转换为邻接矩阵以进行层次聚类?

问题描述

我有一个代码可以生成一个由分号分隔的 CSV 文件,没有空格也没有标题。但是,CSV 包含一系列字符串和浮点值。字符串是文件名称。 CSV 数据如下所示:

folder_a;folder_b;33.9
folder_b;folder_c;89.4
folder_a;folder_c;90.2

我的最终目标是将这组 csv 数据转换为邻接矩阵,以便我可以将其输入到 Scikit 中进行层次聚类。

CSV 结果的每一行都记录了文件名称(folder_x 和 folder_y)和一个对应的值(您可以将其视为编辑距离百分比,这意味着不需要归一化)。换句话说,CSV 数据提供了填充邻接矩阵所需的值(或者更具体地说,它是一个最小编辑距离表):

ID 一个 b c
0 33.9 90.2
b 33.9 0 89.4
c 90.2 89.4 0

我不确定我应该在这里采取什么方法。我应该如何将这些 CSV 数据转换为可以输入 Scikit 的邻接矩阵?请注意,对角线应始终为 0,并且相应的文件夹对(例如 (a,b) 和 (b,a))应具有相同的值。

我知道这里有一个问题 (CSV to adjacency matrix),但似乎作者真的想将其转换为普通数组而不是邻接矩阵。

解决方法

注意:这可能不是一种有效的方法。

给定数据框

df = pd.DataFrame({'col1': {0: 'folder_a',1: 'folder_b',2: 'folder_a'},'col2': {0: 'folder_b',1: 'folder_c',2: 'folder_c'},'col3': {0: 33.9,1: 89.4,2: 90.2}})
      col1      col2        col3
0     folder_a  folder_b    33.9
1     folder_b  folder_c    89.4
2     folder_a  folder_c    90.2
import pandas as pd
import numpy as np


# create a dictionary ex: {(folder_a,folder_b,col3):33.9,...etc}
mapped = df.set_index(['col1','col2']).stack().to_dict()

# mat will store the corresponding values of all combinations
mat = []
unique_values = np.unique(df[['col1','col2']])
for i in unique_values:
    temp = []
    for j in unique_values:
        # now get the value of this combination from the dict made earlier
        val = mapped.get((i,j,'col3')) or mapped.get((j,i,'col3'))
        val = 0 if  val == None else val
        temp.append(val)
    mat.append(temp)
    
df2 = pd.DataFrame(mat,columns=unique_values,index = unique_values)

输出

            folder_a    folder_b    folder_c
folder_a    0.0         33.9        90.2
folder_b    33.9        0.0         89.4
folder_c    90.2        89.4        0.0
,

您可以使用pandas.pivot_table

使用与@Epsi95 的答案相同的数据帧,但在您的情况下,您可以使用 df = pd.read_csv('test2.csv',sep=';',header=None)

将 .csv 输入到熊猫中
import pandas as pd

df = pd.DataFrame({'col1': {0: 'folder_a',2: 90.2}})

首先,创建一个反射的df并添加

reflected_df = pd.DataFrame(df[['col2','col1','col3']].values,columns = ['col1','col2','col3'])
df = df.append(reflected_df)

然后添加对角线零

for folder in pd.concat([df['col1'],df['col2']]).unique():
    df = df.append({'col1':folder,'col2':folder,'col3':0.0},ignore_index=True)

最后可以通过使用pivot_table

得到想要的结果
df['col3'] = df['col3'].astype(float)

table = pd.pivot_table(df,values='col3',index = 'col1',columns='col2')