9

経度値 (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]

複数の一致があるため、最後の行はエラーをスローします。現時点では、値を 1 つだけ見つける方法がわかりません。最初の値としましょう。どんな助けでも大歓迎です!

4

6 に答える 6

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 に保存する必要があります。

于 2011-05-18T13:34:05.287 に答える
6
min(itertools.izip(Lat, Lon), key=operator.itemgetter(1))[0]
于 2011-05-18T12:31:06.297 に答える
4

これを解決するための多くの代替手段の1つに飛びつくのではなく(他の回答で見ることができます)、元の例のコードがなぜ遅いのかを列挙する価値があります.

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

OPから、len(Lon) == 420481. ここで、最小値を見つけることは O(N) 操作です (すべての値を少なくとも 1 回は確認する必要があります)。リスト内包表記では、条件は反復ごとに再評価されます。上記のコードは、ループを通過するたびに最小値を再計算し、O(N) 操作であるべきものを O(N^2) に吹き飛ばします (この場合、わずか 1770回の反復)。

繰り返しごとに結果を再計算する代わりに、単に結果をmin(Lon)ローカル変数にキャッシュし、それをループ条件で使用すると、ランタイムが許容レベルにまで低下する可能性があります。

ただし、私が個人的に行う方法は次のとおりです(後で緯度、経度、およびインデックスのすべてが必要であると仮定します):

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

ただし、多くの可能性があり、どれが最適かは正確なユース ケースによって異なります。

于 2011-05-18T13:39:27.387 に答える
0
pairs = zip(latitudes, longitudes)
minLonPair = min(pairs, key=lambda p:p[1])
print(minLonPair[0])

Ignacio のソリューションによると、python2 を使用している場合izipは、zip. ただし、これは python2 で行うすべてのことに当てはまります。

于 2011-05-18T12:30:52.643 に答える
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 値で複数の一致が許可されているように見えます。このため、ワンライナーはないと思います。秘訣は、緯度と経度のペアごとに 1 回ではなく、min(lons) を 1 回だけ見つけたいということです。

>>> 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)]

ラムダ引数 minlon は一度だけ計算する必要があるため、このワンライナーはうまくいくかもしれません:

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

ただし、420481 要素のリストでどれだけうまく機能するかはわかりません。読みやすさと長期的なサポートのために、私はおそらくより明示的な 2 ライナー ソリューションを選択します。

最後のポイント: イテレーターの場合やジェネレーターの出力の場合など、シーケンスを介して 1 つのパスしか得られない場合があります。複数の一致をサポートし、2 つのリストを 1 回だけ通過させるには、これが最善の方法でした。

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])
于 2011-05-18T12:32:45.020 に答える
0

最初にインデックスを見つけてください:

index = min(enumerate(Lon), key=operator.itemgetter(1))[1] 
Lat[index]
于 2011-05-18T12:36:53.417 に答える