gpt4 book ai didi

Python:如何计算两个网络之间的杰卡德指数?

转载 作者:行者123 更新时间:2023-12-01 09:22:53 27 4
gpt4 key购买 nike

我有两个数据帧df1df2,其中包含两个网络g1g2的边缘列表,其中包含相同的节点但不同的连接。对于每个节点,我想比较两个网络之间的 jaccard 索引。

我定义了计算 jaccard 指数的函数

def compute_jaccard_index(set_1, set_2):
n = len(set_1.intersection(set_2))
return n / float(len(set_1) + len(set_2) - n)

df1
i j
0 0 2
1 0 5
2 1 2
3 2 3
4 2 4
5 2 7


df2
i j
0 0 2
1 0 5
2 0 1
3 1 3
4 2 4
5 2 7

我正在做的事情如下:

tmp1 = pd.unique(df1['i'])
tmp2 = pd.unique(df2['i'])

JI = []
for i in tmp1:
tmp11 = df1[df1['i']==i]
tmp22 = df2[df2['i']==i]
set_1 = list(tmp11['j'])
set_2 = list(tmp22['j'])

JI.append(compute_jaccard_index(set_1, set_2))

我想知道是否有更有效的方法

最佳答案

我总是发现利用 scipy 的稀疏矩阵并对运算进行矢量化比依赖 python 的集合函数更快。这是一个简单的函数,可以隐藏DataFrame 边缘列表为稀疏矩阵(有向和无向):

import scipy.sparse as spar

def sparse_adjmat(df, N=None, directed=False, coli='i', colj='j'):
# figure out size of matrix if not given
if N is None:
N = df[[coli, colj]].max() + 1

# make a directed sparse adj matrix
adjmat = spar.csr_matrix((np.ones(df.shape[0],dtype=int), (df[coli].values, df[colj].values)), shape = (N,N))

# for undirected graphs, force the adj matrix to be symmetric
if not directed:
adjmat[df[colj].values, df[coli].values] = 1

return adjmat

那么这只是二元邻接矩阵上的简单向量运算:

def sparse_jaccard(m1,m2):

intersection = m1.multiply(m2).sum(axis=1)
a = m1.sum(axis=1)
b = m2.sum(axis=1)
jaccard = intersection/(a+b-intersection)

# force jaccard to be 0 even when a+b-intersection is 0
jaccard.data = np.nan_to_num(jaccard.data)
return np.array(jaccard).flatten()

为了进行比较,我制作了一个随机的 pandas 边缘列表函数,并将您的代码包装到以下函数中:

def erdos_renyi_df(N=100,m=400):
df = pd.DataFrame(np.random.randint(0,N, size=(m,2)), columns = ['i','j'])
df.drop_duplicates(['i','j'], inplace=True)
df.sort_values(['i','j'], inplace=True)
df.reset_index(inplace=True, drop=True)
return df

def compute_jaccard_index(set_1, set_2):
n = len(set_1.intersection(set_2))
return n / float(len(set_1) + len(set_2) - n)

def set_based_jaccard(df1,df2):
tmp1 = pd.unique(df1['i'])
tmp2 = pd.unique(df2['i'])
JI = []
for i in tmp1:
tmp11 = df1[df1['i']==i]
tmp22 = df2[df2['i']==i]
set_1 = set(tmp11['j'])
set_2 = set(tmp22['j'])

JI.append(compute_jaccard_index(set_1, set_2))

return JI

然后我们可以通过创建两个随机网络来比较运行时间:

N = 10**3
m = 4*N

df1 = erdos_renyi_df(N,m)
df2 = erdos_renyi_df(N,m)

并使用基于集合的方法计算每个节点的 Jaccard 相似度:

%timeit set_based_jaccard(df1,df2)
1.54 s ± 113 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

以及稀疏方法(包括转换为稀疏矩阵的开销):

%timeit sparse_jaccard(sparse_adjmat(df1, N=N, directed=True, coli='i', colj='j'),sparse_adjmat(df2, N=N, directed=True, coli='i', colj='j'))
1.71 ms ± 109 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

如您所见,稀疏矩阵代码的速度大约快 1000 倍。

关于Python:如何计算两个网络之间的杰卡德指数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50683128/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com