通过使用字符串列的子集比较所有行来创建邻接矩阵
Create adjacency matrix by comparing all rows using a subset of string columns
我有一个包含三列的 Pandas 数据框,id
(唯一标识符),然后是三个字符串列 event_one
、event_two
和 event_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 对,将测试每个事件列中的字符串相等性,然后计算匹配事件占总数的比例事件数。
例如,如果我们将 N1
与 N5
进行比较,则该对的邻接矩阵中的关联条目将为 2/3(或 0.66..),因为它们在 event_one
和 event_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
我有一个包含三列的 Pandas 数据框,id
(唯一标识符),然后是三个字符串列 event_one
、event_two
和 event_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 对,将测试每个事件列中的字符串相等性,然后计算匹配事件占总数的比例事件数。
例如,如果我们将 N1
与 N5
进行比较,则该对的邻接矩阵中的关联条目将为 2/3(或 0.66..),因为它们在 event_one
和 event_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