在long vector,python中获得最小值索引的有效方法

时间:2011-05-18 12:26:48

标签: python list indexing latitude-longitude minimum

我有一长串的经度值(len(Lon)= 420481)和另一个纬度值。我想找到相应纬度到经度的最小值。

我试过了:

SE_Lat = [Lat[x] for x,y in enumerate(Lon) if y == min(Lon)]

但这需要很长时间才能完成。

有谁知道更有效的方式?

也许您对此也有建议: 我现在尝试找到与新经度最接近的相应纬度,该经度不在原始经度向量中。我试过这个:

minDiff = [min(abs(x - lon_new) for x in lons)] # not very quick, but works
[(lat,lon) for lat,lon in izip(lats,lons) if abs(lon-lon_new)==minDiff]

最后一行会抛出错误,因为有多个匹配项。我现在不知道如何只找到一个值,让我们说第一个。非常感谢任何帮助!

6 个答案:

答案 0 :(得分:7)

我可以推荐numpy吗?

import numpy
nplats = numpy.array(lats)
nplons = numpy.array(lons)

# this part is 20x faster than using the built-in python functions
index = numpy.argmin(nplats)

print nplats[index], nplons[index]

这比min(izip())解决方案快(使用420481随机创建的记录时使用我的设置大约20倍),虽然当然你需要将数据值存储在numpy中以利用这个速度-up。

答案 1 :(得分:6)

min(itertools.izip(Lat, Lon), key=operator.itemgetter(1))[0]

答案 2 :(得分:4)

不是直接使用其中一个替代解决方案(可以在其他答案中看到),而是值得枚举为什么原始示例中的代码是如此慢。< / p>

SE_Lat = [Lat[x] for x,y in enumerate(Lon) if y == min(Lon)]

我们从OP了解len(Lon) == 420481。现在,找到最小值是O(N)操作(您必须至少查看一次每个值)。在列表推导中,在每次迭代上重新评估条件。上面的代码重新计算了每次通过循环的最小值,将O(N)操作应该是O(N ^ 2)(在这种情况下仅仅是177 十亿次迭代)

简单地将min(Lon)的结果缓存在局部变量中并在循环条件中使用它而不是每次迭代重新计算它可能会使运行时降低到可接受的水平。

然而,我个人会这样做(假设我以后想要所有的纬度,经度和指数):

min_longitude, min_index = min(longitude, index for index, longitude in enumerate(Lon))
min_latitude = Lat[min_index]

虽然有很多可能性,但哪一个最好会因具体用例而异。

答案 3 :(得分:0)

pairs = zip(latitudes, longitudes)
minLonPair = min(pairs, key=lambda p:p[1])
print(minLonPair[0])

根据Ignacio的解决方案,如果您使用的是python2,则需要使用izip而不是zip。但是,对于你在python2中所做的一切都是如此。

答案 4 :(得分:0)

这是我原来的答案:

>>> lats = [1,2,3,4]
>>> lons = [5,4,8,9]
>>> from itertools import izip
>>> min(izip(lats,lons), key=lambda x:x[1])
(2, 4)

但是我看到OP似乎允许在最小lon值处存在多个匹配,为此,我认为没有一个单行。诀窍是,你只想找到一次min(lons),而不是每一个lat,lon对一次:

>>> lats = [1,2,3,4]
>>> lons = [5,4,8,4]
>>> minlon = min(lons)
>>> [(lat,lon) for lat,lon in izip(lats,lons) if lon==minlon]
[(2, 4), (4, 4)]

这个单行可能对你有用,因为lambda参数minlon应该只计算一次:

>>> filter(lambda latlon,minlon=min(lons):latlon[1]==minlon, izip(lats,lons))
[(2, 4), (4, 4)]

不确定它在420481元素列表上的效果如何。为了便于阅读和长期支持,我可能会选择更明确的双线解决方案。

最后一点: 有时您只能通过一个序列,例如当它是迭代器或生成器的输出时。为了支持多个匹配并且只通过两个列表,这是我能做的最好的事情:

from itertools import izip

def get_lats_at_min_lon(lats, lons):
    minlon = 200
    minlats = []
    for lat,lon in izip(lats, lons):
        if lon < minlon:
            minlats = [lat]
            minlon = lon
        elif lon == minlon:
            minlats.append(lat)
    return minlon, minlats

lats = iter([1,2,3,4])
lons = iter([5,4,8,4])

print get_lats_at_min_lon(lats,lons)

打印:

(4, [2, 4])

答案 5 :(得分:0)

首先找到索引:

index = min(enumerate(Lon), key=operator.itemgetter(1))[1] 
Lat[index]