使用pandas DataFrame行的组合填充"计数矩阵"

EB2*_*127 4 python count matrix dataframe pandas

假设我在Python3.x中有以下pandas DataFrame

import pandas as pd

dict1 = {'name':['dog', 'dog', 'cat', 'cat', 'cat', 'bird', 'bird', 'bird', 'bird'], 'number':[42, 42, 42, 42, 42, 42, 42, 42, 42], 'count':[1, 2, 4, 5, 7, 1, 2, 5, 8]} 
df = pd.DataFrame(dict1)

print(df)
##    name  number  count
## 0   dog      42      1
## 1   dog      42      2
## 2   cat      42      4
## 3   cat      42      5
## 4   cat      42      7
## 5  bird      42      1
## 6  bird      42      2
## 7  bird      42      5
## 8  bird      42      8
Run Code Online (Sandbox Code Playgroud)

counts包含1到8的整数.我的目标是在给定列中的唯一类别的情况下,使用每个组合"对"的计数填充8乘8的零矩阵name.

因此,对于组合对dog,catbird是:

dog: (1, 2)
cat: (4, 5), (4, 7), (5, 7)
bird: (1, 2), (1, 5), (1, 8), (2, 5), (2, 8), (5, 8)
Run Code Online (Sandbox Code Playgroud)

对于每一对,我添加+1到零矩阵中的相应条目.

该矩阵将是对称的,即(n, m) = (m, n).给出的矩阵df是:

   1 2 3 4 5 6 7 8
1: 0 2 0 0 1 0 0 1
2: 2 0 0 0 1 0 0 1
3: 0 0 0 0 0 0 0 0
4: 0 0 0 0 1 0 1 0
5: 1 1 0 1 0 0 1 1
6: 0 0 0 0 0 0 0 0
7: 0 0 0 1 1 0 0 0
8: 1 1 0 0 1 0 0 0
Run Code Online (Sandbox Code Playgroud)

请注意,组合和组合(1,2)=(2,1)的计数为2 .dogbird

(1)为了做到这一点,我认为最好在给定pandas DataFrame的情况下创建一个"组合元组"列表.

就是这样的

list_combos = [(1, 2), (2, 1), (4, 5), (4, 7), (5, 7), (5, 4), (7, 4), (7, 5),
    (1, 2), (1, 5), (1, 8), (2, 5), (2, 8), (5, 8), (2, 1), (5, 1),
    (8, 1), (5, 2), (8, 2), (8, 5)]
Run Code Online (Sandbox Code Playgroud)

鉴于矩阵是对称的,也许最好使用:

list_combos2 = [(1, 2), (4, 5), (4, 7), (5, 7), (1, 2), (1, 5), (1, 8), (2, 5), (2, 8), (5, 8)]
Run Code Online (Sandbox Code Playgroud)

考虑到"名字"中的分类值,如何计算pandas DataFrame中entires的排列?

(2)在给定元组列表的情况下,填充此矩阵的算法效率最高(即RAM)是多少?

我应该能够将一个元组列表提供给一个numpy数组,但是如何填充零?

cs9*_*s95 6

您可以使用groupby,迭代组合,并像这样构建矩阵:

import numpy as np
from itertools import combinations

mat = np.zeros((df['count'].max(), ) * 2)
idx = []
for _, g in df.groupby('name'):
    idx.extend(combinations(g['count'] - 1, r=2))

np.add.at(mat, list(zip(*idx)), 1)
mat += mat.T

array([[0., 2., 0., 0., 1., 0., 0., 1.],
       [2., 0., 0., 0., 1., 0., 0., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 1., 0.],
       [1., 1., 0., 1., 0., 0., 1., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 1., 0., 0., 0.],
       [1., 1., 0., 0., 1., 0., 0., 0.]])
Run Code Online (Sandbox Code Playgroud)

可能是一个更快的解决方案,但是这是我能想到的最干净的一个.

  • 打败了我:)我还建议存储完整的矩阵是没有价值的,因为它是对称的,没有对角线.相比之下,如果内存/性能很重要,只存储顶部三角形? (2认同)