通过使用字符串列的子集比较所有行来创建邻接矩阵

Create adjacency matrix by comparing all rows using a subset of string columns

我有一个包含三列的 Pandas 数据框,id(唯一标识符),然后是三个字符串列 event_oneevent_twoevent_three ,如下:

test_df.head()

    id  event_one  event_two  event_three
0   N1  'aaa'      'abc'      'xyz'
1   N2  'bbb'      'abc'      'uvw'
2   N3  'ccc'      'def'      'xyz'
3   N4  'aaa'      'def'      'uvw'
4   N5  'aaa'      'abc'      'zzz'

我想创建一个邻接矩阵(作为数据框),对于所有 ID 对,将测试每个事件列中的字符串相等性,然后计算匹配事件占总数的比例事件数。

例如,如果我们将 N1N5 进行比较,则该对的邻接矩阵中的关联条目将为 2/3(或 0.66..),因为它们在 event_oneevent_two,但不是 event_three

使用上面的 test_df 示例,最终的邻接矩阵(表示为 Pandas 数据框)如下所示:

      N1    N2    N3    N4    N5
      ----------------------------
N1|   -     1/3   1/3   1/3   2/3
N2|   1/3   -     0     1/3   1/3
N3|   1/3   0     -     1/3   0
N4|   1/3   1/3   1/3   -     1/3
N5|   2/3   1/3   0     1/3   -

到目前为止我编写的代码(见下文)使用 pdist 和 lambda 表达式,但仅基于 event_one。如何将其扩展到所有三个事件列,然后计算最终计算结果,或者有更好的方法吗?

import pandas as pd
from scipy.spatial.distance import pdist, squareform

# Create the example dataframe
events = {'id': ['N1', 'N2', 'N3', 'N4', 'N5'], 
          'event_one': ['aaa', 'bbb', 'ccc', 'aaa', 'aaa'],
          'event_two': ['abc', 'abc', 'def', 'def', 'abc'],
          'event_three': ['xyz', 'uvw', 'xyz', 'uvw', 'zzz']}
df = pd.DataFrame(events, columns=['id', 'event_one', 'event_two', 'event_three'])

# Create an adjacency matrix by comparing event_one using pdist

index_ndarray = df['id'].values
event_one_series = df['event_one']
dm = pdist(event_one_series[:, None], lambda u, v: 1 if u == v else 0)
event_one_matrix_df = pd.DataFrame(
    squareform(dm),
    dtype='str',
    index=index_ndarray,
    columns=index_ndarray)
event_one_matrix_df

    N1      N2      N3      N4      N5
N1  0.0     0.0     0.0     1.0     1.0
N2  0.0     0.0     0.0     0.0     0.0
N3  0.0     0.0     0.0     0.0     0.0
N4  1.0     0.0     0.0     0.0     1.0
N5  1.0     0.0     0.0     1.0     0.0

有什么建议就太好了,谢谢。

让我们使用 filter to select the event like columns, then use pdist 并传递自定义 lambda 函数 f,该函数比较成对的行和 returns 匹配的事件分数:

from scipy.spatial.distance import pdist, squareform

f = lambda u, v: (u == v).sum() / len(u)
a = squareform(pdist(df.filter(like='event'), f))
d = pd.DataFrame(a, index=df['id'].tolist(), columns=df['id'].tolist())

print(d)
         N1        N2        N3        N4        N5
N1  0.000000  0.333333  0.333333  0.333333  0.666667
N2  0.333333  0.000000  0.000000  0.333333  0.333333
N3  0.333333  0.000000  0.000000  0.333333  0.000000
N4  0.333333  0.333333  0.333333  0.000000  0.333333
N5  0.666667  0.333333  0.000000  0.333333  0.000000