我编写的这段代码可以使用,但需要很长时间(约8小时)才能完成执行。
想知道是否可以优化它以更快地执行。
目的是根据彼此的距离对大量物品(x,y,z)进行分组。例如;
我想将它们分组为x中的+ -0.5,y中的+ -0.5和z中的+ -0.5,然后下面数据的输出将为[(0,3),(1),(2,4)...]
。
x y z
0 1000.1 20.2 93.1
1 647.7 91.7 87.7
2 941.2 44.3 50.6
3 1000.3 20.3 92.9
4 941.6 44.1 50.6
...
我所做的(以及哪些有效)描述如下。
它将data_frame
的第一行与第2,第3,第4行比较直到结束,并且对于每一行,如果距离x to x < +-0.5 and y to y < +-0.5 and z to z < +- 0.5
然后将索引添加到列表中,group
。如果它没有,则它比较下一行直到到达循环结束。
每个循环完成后,匹配(存储在group
)中的索引将作为一个集添加到另一个列表groups
中,然后从原始列表a
中删除,然后比较下一个a[0]
,依此类推。
groups = []
group = []
data = [(x,y,z),(x,y,z),(etc)] # > 50,000 entries
data_frame = pd.DataFrame(data, columns=['x','y','z'])
a = list(i for i in range(len(data_frame)))
threshold = 0.5
for j in range(len(a) - 1) :
if len(a) > 0:
group.append(a[0])
for ii in range(a[0], len(data_frame) - 1):
if ((data_frame.loc[a[0],'x'] - data_frame.loc[ii,'x']) < threshold) and ((data_frame.loc[a[0],'y'] - data_frame.loc[ii,'y']) < threshold) and ((data_frame.loc[a[0],'z'] - data_frame.loc[ii,'z']) < threshold):
group.append(ii)
else:
continue
groups.append(set(group))
for iii in group:
if iii in a:
a.remove(iii)
else:
continue
group = []
else:
break
返回类似的东西,例如;
groups = [{0}, {1, 69}, {2, 70}, {3, 67}, {4}, {5}, {6}, {7, 9}, {8}, {10}, {11}, {12}, 13}, {14, 73}, {15}, {16}, {17, 21, 74}, {18, 20}, {19}, {22, 23}]
对这个问题做了很多编辑,因为它不是很清楚。希望现在有意义。
以下是尝试使用更好的逻辑&#O;(NlogN)&#39;哪个更快,但没有返回正确的答案。对x,y,z使用了相同的+ -0.5。
编辑:
test_list = [(i,x,y,z), ... , (i,x,y,z)]
df3 = sorted(test_list,key=lambda x: x[1])
result = []
while df3:
if len(df3) > 1: ####added this because was crashing at the end of the loop
a = df3.pop(0)
alist=[a[0]]
while ((abs(a[1] - df3[0][1]) < 0.5) and (abs(a[2] - df3[0][2]) < 0.5) and (abs(a[3] - df3[0][3]) < 0.5)):
alist.append(df3.pop(0)[0])
if df3:
continue
else:
break
result.append(alist)
else:
result.append(a[0])
break
答案 0 :(得分:1)
由于您要将每个数据点与每个数据点进行比较,因此您的实现的时间复杂度最差为O(N!)。更好的方法是先进行排序。
import random
df = [i for i in range(100)]
random.shuffle(df)
df2 = [(i,x) for i,x in enumerate(df)]
df3 = sorted(df2,key=lambda x: x[1])
df3
[(31, 0), (24, 1), (83, 2)......
假设您现在要将+ 5 / -5的组号分组到一个列表中。然后,您可以根据条件将数字切片到列表中。
result = []
while df3:
a = df3.pop(0)
alist=[a[0]]
while a[1] + 5 >= df3[0][1]:
alist.append(df3.pop(0)[0])
if df3:
continue
else:
break
result.append(alist)
result
[[31, 24, 83, 58, 82, 35], [0, 65, 77, 41, 67, 56].......
排序需要O(NlogN),分组基本上需要线性时间。所以这比N要快得多!