请参阅此问题底部的重要说明。
我正在使用 numpy 来加速经度/纬度坐标的一些处理。不幸的是,我的 numpy“优化”使我的代码运行速度提高了大约 5 倍slowly比它在不使用 numpy 的情况下运行。
瓶颈似乎在于用我的数据填充 numpy 数组,然后在完成数学转换后提取该数据。为了填充数组,我基本上有一个像这样的循环:
point_list = GetMyPoints() # returns a long list of ( lon, lat ) coordinate pairs
n = len( point_list )
point_buffer = numpy.empty( ( n, 2 ), numpy.float32 )
for point_index in xrange( 0, n ):
point_buffer[ point_index ] = point_list[ point_index ]
该循环仅在对其进行操作之前填充 numpy 数组,速度非常慢,比没有 numpy 的整个计算慢得多。 (也就是说,这不仅仅是 python 循环本身的缓慢,而且显然在实际将每个小数据块从 python 传输到 numpy 时存在巨大的开销。)另一端也有类似的缓慢;处理完 numpy 数组后,我在循环中访问每个修改的坐标对,再次如下
some_python_tuple = point_buffer[ index ]
同样,提取数据的循环比没有 numpy 的整个原始计算慢得多。那么,我如何实际填充 numpy 数组并从 numpy 数组中提取数据,而不会违背首先使用 numpy 的目的?
我正在使用 C 库从形状文件中读取数据,该库将数据作为常规 python 列表提供。我知道,如果库向我提供了 numpy 数组中已有的坐标,则不需要“填充”numpy 数组。但不幸的是,我的数据起点是一个常规的 python 列表。更重要的是,一般来说,我想了解如何使用 python 中的数据快速填充 numpy 数组。
澄清
上面显示的循环实际上过于简单化了。我在这个问题中这样写是因为我想专注于我所看到的尝试在循环中缓慢填充 numpy 数组的问题。我现在明白这样做只是缓慢的。
在我的实际应用程序中,我拥有的是坐标点的形状文件,并且我有一个 API 来检索给定对象的点。大约有 200,000 个对象。所以我反复调用一个函数GetShapeCoords( i )
获取对象 i 的坐标。这将返回一个列表列表,其中每个子列表都是经度/纬度对的列表,它是列表列表的原因是某些对象是多部分的(即多多边形)。然后,在我的原始代码中,当我读取每个对象的点时,我通过调用常规 python 函数对每个点进行转换,然后使用 PIL 绘制转换后的点。整个过程花了大约 20 秒来绘制所有 200,000 个多边形。并不可怕,但还有很大的改进空间。我注意到这 20 秒中至少有一半花在了转换逻辑上,所以我想我应该在 numpy 中这样做。我最初的实现只是一次读入一个对象,然后将子列表中的所有点不断附加到一个大的 numpy 数组中,然后我可以在 numpy 中进行数学运算。
所以,我现在明白,简单地将整个 python 列表传递给 numpy 是设置大数组的正确方法。但就我而言,我一次只读取一个对象。所以我能做的一件事就是在一个大的Python列表列表中不断地添加点。然后,当我以这种方式编译了一些大量对象的点(例如 10000 个对象)时,我可以简单地将怪物列表分配给 numpy。
所以我现在的问题是三个部分:
(a) numpy 真的可以接受那么大的、不规则形状的列表列表,并快速快速地读取它吗?
(b) 然后我希望能够变换该怪物树叶子中的所有点。例如,获取 numpy 的表达式是什么,“进入每个子列表,然后进入每个子子列表,然后对于在这些子子列表中找到的每个坐标对,将第一个(lon 坐标)乘以 0.5”?我可以这样做吗?
(c) 最后,我需要取回这些转换后的坐标以便绘制它们。
下面温斯顿的回答似乎暗示了我如何使用 itertools 来完成这一切。我想做的与温斯顿所做的非常相似,将列表展平。但我不能完全把它弄平。当我去绘制数据时,我需要能够知道一个多边形何时停止以及下一个多边形何时开始。所以,我认为如果有一种方法可以用特殊的坐标对(例如(-1000,-1000)或类似的东西)快速标记每个多边形(即每个子列表)的末端,我就可以让它工作。然后我可以像温斯顿的答案一样用 itertools 进行展平,然后在 numpy 中进行转换。然后我需要使用 PIL 从点到点进行实际绘制,在这里我想我需要将修改后的 numpy 数组重新分配回 python 列表,然后在常规 python 循环中迭代该列表来进行绘图。除了编写一个 C 模块来一步处理所有阅读和绘图之外,这似乎是我的最佳选择吗?