python - 如何将簇/类/组标签的数据框转换为成对/不成对的成对数据框?

标签 python pandas numpy transform transpose

我试图找到聚类结果之间的一致性,但我很难有效地做到这一点。我想转换 i=nodej=iterationpandas DataFrame 对象(或字典),以及[i,j]=集群/组。我当前的方法是迭代所有可能性,但我觉得有一种更有效的方法来做到这一点。对于大型数据集来说,这将需要很长时间。

import string
import pandas as pd
import numpy as np
from collections import *

# Get alphabet as nodes
nodes = list(string.ascii_lowercase)

data = {0: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 1: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 2: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 3: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 4: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 5: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 6: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 7: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 8: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}, 9: {'a': 0, 'b': 0, 'c': 0, 'd': 1, 'e': 0, 'f': 0, 'g': 2, 'h': 0, 'i': 0, 'j': 0, 'k': 0, 'l': 0, 'm': 3, 'n': 0, 'o': 4, 'p': 0, 'q': 0, 'r': 3, 's': 0, 't': 0, 'u': 0, 'v': 4, 'w': 2, 'x': 2, 'y': 1, 'z': 0}} 
df_clusters = pd.DataFrame(data)

enter image description here

如何更有效地完成这部分而不是暴力迭代?有没有办法利用 NumPy 数组来实现此目的?

# Get pairs of nodes and determine if they are in the same cluster/community/group
d_pair_iteration = defaultdict(dict)
for iteration, communities in df_clusters.T.iterrows():
    # Iterate pairwise
    for i in range(len(nodes)):
        # Node A
        node_a = nodes[i]
        for j in range(i+1, len(nodes)):
            # Node B
            node_b = nodes[j]
            # Determine if they are in the same community
            d_pair_iteration[frozenset([node_a, node_b])][iteration] = int(communities[node_a] == communities[node_b])

# Create dataframe
df_pairs = pd.DataFrame(d_pair_iteration).T

enter image description here

最佳答案

使用 numpy 广播,我们可以将行 a 与整个数据帧进行比较,然后将 b 与整个数据帧进行比较,依此类推:

# `x` is a table of 26 rows and 10 columns
x = df_clusters.values

# `y` is an array of 26 tables, each having 1 row and 10 columns
y = x[:, None]

# Using numpy broadcasting, `z` contains the result of comparing each
# table in `y` against `x`. So the shape of `z` is 26 x 26 x 10
z = x == y

# Reshaping `z` by merging the first two dimensions
data = z.reshape((z.shape[0] * z.shape[1], z.shape[2])).astype('int')

# idx is the 2-permutation of values in `df_clusters.index`:
# (a,a), (a,b), ..., (a,z), (b,a), (b,b), ...
idx = pd.MultiIndex.from_product([df_clusters.index, df_clusters.index], names=['node1', 'node2'])
result = pd.DataFrame(data, index=idx, columns=df_clusters.columns)

# We don't want all permutations, only the unique combinations,
# so we have to slice the frame
from itertools import combinations
final_idx = list(combinations(df_clusters.index, 2))
result = result.loc[final_idx]

结果是一个 325 x 10 数据帧,因为 C(26, 2) = 325。这是一个小样本:

             0  1  2  3  4  5  6  7  8  9
node1 node2                              
a     b      1  1  1  1  1  1  1  1  1  1
      c      1  1  1  1  1  1  1  1  1  1
      d      0  0  0  0  0  0  0  0  0  0
      e      1  1  1  1  1  1  1  1  1  1
      f      1  1  1  1  1  1  1  1  1  1

关于python - 如何将簇/类/组标签的数据框转换为成对/不成对的成对数据框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58566957/

相关文章:

python - 当在 Pygame 中使用 colorkey 透明度位 block 分割 Sprite 时,应该透明的区域是黑色的

python - 从数据框 Python 中删除子字符串

python - 迭代一组 URL 并收集 CSV 格式的数据输出

python - 获取与值匹配的数组元素的索引

python - 环路和 fork 图

python - 如何 reshape 包含图像数据的数组

c++ - python/c++ - 使用 cmake 编译共享库并使用 distutils 安装

python - 使用 Python 在 MS Office 文档中嵌入对象?

python - 如何在特定行上旋转 Pandas 数据框

python - 用 imshow 绘制的时间序列