data
是一个列表,其中每个条目都是一个浮动列表
L
是检查_
中data
的第一个条目是否相等的范围,如果是,则将其存储在c
<中的该索引处/ p>
c = []
d = []
for i in range(L):
for seq in data:
if int(seq[0]) == i:
d.append(seq)
c.append(d)
d = []
return c
>>> data = [[4.0, 0.0, 15.0, 67.0], [3.0, 0.0, 15.0, 72.0], [4.0, 0.0, 15.0, 70.0], [1.0, -0.0, 15.0, 90.0], [3.0, -0.0, 15.0, 75.0], [2.0, -0.0, 15.0, 83.0], [3.0, 0.0, 15.0, 74.0], [4.0, 0.0, 15.0, 69.0], [4.0, 0.0, 14.0, 61.0], [3.0, 0.0, 15.0, 74.0], [3.0, 0.0, 15.0, 75.0], [4.0, 0.0, 15.0, 67.0], [5.0, 0.0, 14.0, 45.0], [6.0, 0.0, 13.0, 30.0], [3.0, 0.0, 15.0, 74.0], [4.0, 0.0, 15.0, 55.0], [7.0, 0.0, 13.0, 22.0], [6.0, 0.0, 13.0, 25.0], [1.0, -0.0, 15.0, 83.0], [7.0, 0.0, 13.0, 18.0]]
>>> sort(data,7)
[[], [[1.0, -0.0, 15.0, 90.0], [1.0, -0.0, 15.0, 83.0]], [[2.0, -0.0, 15.0, 83.0]], [[3.0, 0.0, 15.0, 72.0], [3.0, -0.0, 15.0, 75.0], [3.0, 0.0, 15.0, 74.0], [3.0, 0.0, 15.0, 74.0], [3.0, 0.0, 15.0, 75.0], [3.0, 0.0, 15.0, 74.0]], [[4.0, 0.0, 15.0, 67.0], [4.0, 0.0, 15.0, 70.0], [4.0, 0.0, 15.0, 69.0], [4.0, 0.0, 14.0, 61.0], [4.0, 0.0, 15.0, 67.0], [4.0, 0.0, 15.0, 55.0]], [[5.0, 0.0, 14.0, 45.0]], [[6.0, 0.0, 13.0, 30.0], [6.0, 0.0, 13.0, 25.0]]]
len(data)
大约为2百万
L
大约是8000。
我需要一种方法来理想地提高速度!
答案 0 :(得分:0)
假设您要根据每个子列表的第一个值将子列表分类为 buckets 。
为简单起见,我使用以下内容生成随机数进行测试:
L = 10
data = [[round(random.random() * 10.0, 2) for _ in range(3)] for _ in range(10)]
首先关于你的代码,只是为了确保我的意图正确。
c = []
d = []
for i in range(L): # Loop over all buckets
for e in data: # Loop over entire data
if int(e[0]) == i: # If first float of sublist falls into i-th bucket
d.append(e) # Append entire sublist to current bucket
c.append(d) # Append current bucket to list of buckets
d = [] # Reset
这是低效的,因为您遍历每个存储桶的完整数据集。如果您拥有8000
存储桶和2 000 000
浮动列表,那么您将基本上执行16 000 000 000
( 160亿)比较。此外,您可以在创建时完全填充存储桶列表,而不是重复使用data
变量中的现有列表。因此,这会产生尽可能多的数据引用副本。
因此,您应该考虑使用数据的索引,例如
bidx = [int(e[0]) for e in data] # Calculate bucket indices for all sublists
buck = []
for i in range(L): # Loop over all buckets
lidx = [k for k, b in enumerate(bidx) if b == i] # Get sublist indices for this bucket
buck.append([data[l] for l in lidx]) # Collect list references
print(buck)
这应该导致对您的数据进行单次迭代,就地计算存储桶索引。然后,只对你的所有存储桶执行一次迭代,其中从bidx
收集相应的存储区索引(你已经有这个双循环,但这可能会快一些) - 导致lidx
保持data
中属于当前存储桶的子列表的位置。最后,收集桶列表中的列表引用并存储它。
最后一步可能代价高昂,因为它包含大量的参考复制。您应该考虑仅在每个存储桶中存储索引,而不是整个数据,例如
lidx = ...
buck.append(lidx)
如果您的数据很大,所有线性迭代都会很昂贵。您可以尝试尽可能地减少它们,但是数据大小本身定义了较低的上限!
如果必须执行数百万条记录的更多操作,则应考虑更改为其他数据表示形式或格式。例如,如果您需要在一个脚本中执行频繁操作,您可能需要考虑树(例如b树)。如果要将其存储以供进一步处理,您可能需要考虑具有适当索引的数据库。
答案 1 :(得分:0)
在Python 3中运行使用此算法,我获得的性能比jbndlr高2个数量级:
rl = range(L) # Generate the range list
buck = [[] for _ in rl] # Create all the buckets
for seq in data: # Loop over entire data
try:
idx = rl.index(int(seq[0])) # Find the bucket index
buck[idx].append(seq) # Append current data in its bucket
except ValueError:
pass # There is no bucket for that value
将算法与:
进行比较L = 1000
data = [[round(random.random() * 1200.0, 2) for _ in range(3)] for _ in range(100000)]
我明白了:
yours: 26.66 sec
jbndlr: 6.78 sec
mine: 0.07 sec