在python中查找邻居邻居的最有效方法
让我们考虑一下,有两个数组I,并J由此确定邻居对:
I = np.array([0, 0, 1, 2, 2, 3])
J = np.array([1, 2, 0, 0, 3, 2])
这意味着元素0有两个邻居1和2。元素1只有0作为邻居等等。
什么是创建所有邻居三元组阵列的最有效的方式I',J',K'这样j是邻居i和k是邻居j给出的条件i,j以及k不同的元素(i != j != k)?
Ip = np.array([0, 0, 2, 3])
Jp = np.array([2, 2, 0, 2])
Kp = np.array([0, 3, 1, 0])
当然,一种方法是遍历每个元素。有没有更高效的算法?(使用 10-5 亿个元素)
回答
我会采用一种非常简单的方法并使用熊猫(I并且J是您的 numpy 数组):
import pandas as pd
df1 = pd.DataFrame({'I': I, 'J': J})
df2 = df1.rename(columns={'I': 'K', 'J': 'I'})
result = pd.merge(df2, df1, on='I').query('K != J')
优点是pandas.merge依赖于非常快速的底层数值实现。此外,您可以使计算速度更快,例如通过使用索引进行合并。
为了减少这种方法所需要的内存,这将是可能非常有用,减少的规模df1和df2合并之前(例如,通过改变其列D型的东西,适合你的需要)。
以下是如何优化计算速度和内存的示例:
from timeit import timeit
import numpy as np
import pandas as pd
I = np.random.randint(0, 10000, 1000000)
J = np.random.randint(0, 10000, 1000000)
df1_64 = pd.DataFrame({'I': I, 'J': J})
df1_32 = df1_64.astype('int32')
df2_64 = df1_64.rename(columns={'I': 'K', 'J': 'I'})
df2_32 = df1_32.rename(columns={'I': 'K', 'J': 'I'})
timeit(lambda: pd.merge(df2_64, df1_64, on='I').query('K != J'), number=1)
# 18.84
timeit(lambda: pd.merge(df2_32, df1_32, on='I').query('K != J'), number=1)
# 9.28