gpt4 book ai didi

python - numpy数组:快速填充和提取数据

转载 作者:太空狗 更新时间:2023-10-30 02:06:09 24 4
gpt4 key购买 nike

在这个问题的底部可以看到重要的澄清。
我正在使用自动加速,以加速一些经度/纬度坐标的处理。不幸的是,我的NUMPY“优化”使我的代码运行速度比没有使用NUMPY时慢5倍。
瓶颈似乎是用我的数据填充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 ]

这个循环,只是在NUPY数组中填充,甚至在它上运行之前,都非常慢,比整个计算速度慢得多。(也就是说,这不仅仅是Python循环本身的缓慢,而是明显地在实际上将每一小块数据从Python转移到NUMPY的开销)。在另一端,也有类似的慢度;在处理了NUMPY数组之后,我再次访问循环中的每个修改的坐标对。
some_python_tuple = point_buffer[ index ]

同样地,将数据拉出来的循环比没有NUMPY的整个原始计算要慢得多。那么,我如何实际填充numpy数组,并从numpy数组中提取数据,而这种方法一开始并没有违背使用numpy的目的?
我正在使用一个c库从一个形状文件中读取数据,该库将数据作为常规python列表提供给我。我明白,如果图书馆把坐标已经在一个麻木数组中交给了我,那么就没有必要填充NUMPY数组。但不幸的是,对于我来说,数据的起点是作为一个常规的python列表。更重要的是,一般来说,我想了解如何快速用Python中的数据填充一个NUMPY数组。
澄清
上面显示的循环实际上过于简单。在这个问题中,我是这样写的,因为我想把注意力集中在我看到的试图在循环中缓慢填充numpy数组的问题上。我现在明白了,那样做是很慢的。
在我的实际应用程序中,我有一个坐标点的形状文件,我有一个api来检索给定对象的点。大约有20万个物体。因此,我反复调用函数 GetShapeCoords( i )来获取对象i的坐标。这将返回一个列表列表,其中每个子列表是lon/lat对的列表,而列表列表的原因是某些对象是多部分的(即多多边形)。然后,在我的原始代码中,当我读到每个对象的点时,我通过调用一个常规Python函数对每个点进行转换,然后用PIL绘制转换点。整个过程花费了20秒来绘制所有200000个多边形。不可怕,但还有很大的改进空间。我注意到至少20秒的时间花在了转换逻辑上,所以我想我会在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模块来一步完成所有的阅读和绘图之外?

最佳答案

您将数据描述为“坐标列表列表”。我猜你的提取过程如下:

for x in points:
for y in x:
for Z in y:
# z is a tuple with GPS coordinates

执行以下操作:
# initially, points is a list of lists of lists
points = itertools.chain.from_iterable(points)
# now points is an iterable producing lists
points = itertools.chain.from_iterable(points)
# now points is an iterable producing coordinates
points = itertools.chain.from_iterable(points)
# now points is an iterable producing individual floating points values
data = numpy.fromiter(points, float)
# data is a numpy array containing all the coordinates
data = data.reshape( data.size/2,2)
# data has now been reshaped to be an nx2 array

itertools和numpy.fromiter都是用c语言实现的,而且非常高效。因此,这应该可以很快完成转换。
你的问题的第二部分并不能真正说明你想要对数据做什么。索引NUMPY数组速度较慢,然后索引Python列表。通过对数据执行大量操作可以获得速度。如果不知道更多关于这些数据的信息,就很难建议如何修复这些数据。
更新:
我用iTertools和Numpy做了所有的事情。我不负责任何脑损伤造成的尝试,以了解这一代码。
# firstly, we use imap to call GetMyPoints a bunch of times
objects = itertools.imap(GetMyPoints, xrange(100))
# next, we use itertools.chain to flatten it into all of the polygons
polygons = itertools.chain.from_iterable(objects)
# tee gives us two iterators over the polygons
polygons_a, polygons_b = itertools.tee(polygons)
# the lengths will be the length of each polygon
polygon_lengths = itertools.imap(len, polygons_a)
# for the actual points, we'll flatten the polygons into points
points = itertools.chain.from_iterable(polygons_b)
# then we'll flatten the points into values
values = itertools.chain.from_iterable(points)

# package all of that into a numpy array
all_points = numpy.fromiter(values, float)
# reshape the numpy array so we have two values for each coordinate
all_points = all_points.reshape(all_points.size // 2, 2)

# produce an iterator of lengths, but put a zero in front
polygon_positions = itertools.chain([0], polygon_lengths)
# produce another numpy array from this
# however, we take the cumulative sum
# so that each index will be the starting index of a polygon
polygon_positions = numpy.cumsum( numpy.fromiter(polygon_positions, int) )

# now for the transformation
# multiply the first coordinate of every point by *.5
all_points[:,0] *= .5

# now to get it out

# polygon_positions is all of the starting positions
# polygon_postions[1:] is the same, but shifted on forward,
# thus it gives us the end of each slice
# slice makes these all slice objects
slices = itertools.starmap(slice, itertools.izip(polygon_positions, polygon_positions[1:]))
# polygons produces an iterator which uses the slices to fetch
# each polygon
polygons = itertools.imap(all_points.__getitem__, slices)

# just iterate over the polygon normally
# each one will be a slice of the numpy array
for polygon in polygons:
draw_polygon(polygon)

你可能会发现最好一次处理一个多边形。将每个多边形转换为numpy数组并对其执行向量运算。你这样做可能会获得显著的速度优势。把你所有的数据放到numpy中可能有点困难。
这比大多数numpy的东西更难,因为你的数据形状怪异。NUMPY几乎假设了一个形状均一的世界。

关于python - numpy数组:快速填充和提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5559888/

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