2016-11-26 12 views
1

私はPythonを初めて使用していて、このexampleを再構築したいと考えています。私はNYCタクシーのピックアップとドロップオフに関する経度と緯度のデータを持っていますが、データをWeb Mercartorフォーマットに変更する必要があります(これは上記の例では見つかりません)。 私は次のように見え、経度と緯度の値のペアを1つ取り、hereから撮影されたWeb Mercartor形式に変更することができます機能が見つかりました:Pandas Dataframeのすべての行に関数を適用します。

import math 
def toWGS84(xLon, yLat): 
    # Check if coordinate out of range for Latitude/Longitude 
    if (abs(xLon) < 180) and (abs(yLat) > 90): 
     return 

    # Check if coordinate out of range for Web Mercator 
    # 20037508.3427892 is full extent of Web Mercator 
    if (abs(xLon) > 20037508.3427892) or (abs(yLat) > 20037508.3427892): 
     return 

    semimajorAxis = 6378137.0 # WGS84 spheriod semimajor axis 

    latitude = (1.5707963267948966 - (2.0 * math.atan(math.exp((-1.0 * yLat)/semimajorAxis)))) * (180/math.pi) 
    longitude = ((xLon/semimajorAxis) * 57.295779513082323) - ((math.floor((((xLon/semimajorAxis) * 57.295779513082323) + 180.0)/360.0)) * 360.0) 

    return [longitude, latitude] 



def toWebMercator(xLon, yLat): 
    # Check if coordinate out of range for Latitude/Longitude 
    if (abs(xLon) > 180) and (abs(yLat) > 90): 
     return 

    semimajorAxis = 6378137.0 # WGS84 spheriod semimajor axis 
    east = xLon * 0.017453292519943295 
    north = yLat * 0.017453292519943295 

    northing = 3189068.5 * math.log((1.0 + math.sin(north))/(1.0 - math.sin(north))) 
    easting = semimajorAxis * east 

    return [easting, northing] 

def main(): 
    print(toWebMercator(-105.816001, 40.067633)) 
    print(toWGS84(-11779383.349100526, 4875775.395628653)) 

if __name__ == '__main__': 
    main() 

私はすべてのペアに、このデータを適用するにはどうすればよいです私のpandas Dataframeのlong/lat座標系を使用し、出力を同じpandasDFに保存しますか?

df.tail() 
      | longitude  | latitude 
____________|__________________|______________ 
11135465 | -73.986893 | 40.761093 
1113546  | -73.979645 | 40.747814 
11135467 | -74.001244 | 40.743172 
11135468 | -73.997818 | 40.726055 
... 

答えて

1

、最もあなたを助けるだろうか、物事にpandas方法を行う方法を理解することです。行を反復すると、組み込みのベクトル化された方法に比べてひどい性能が得られます。

import pandas as pd 
import numpy as np 

df = pd.read_csv('/yellow_tripdata_2016-06.csv') 
df.head(5) 

VendorID tpep_pickup_datetime tpep_dropoff_datetime passenger_count trip_distance pickup_longitude pickup_latitude RatecodeID store_and_fwd_flag dropoff_longitude dropoff_latitude payment_type fare_amount extra mta_tax tip_amount tolls_amount improvement_surcharge total_amount 
0 2 2016-06-09 21:06:36 2016-06-09 21:13:08 2 0.79 -73.983360 40.760937 1 N -73.977463 40.753979 2 6.0 0.5 0.5 0.00 0.0 0.3 7.30 
1 2 2016-06-09 21:06:36 2016-06-09 21:35:11 1 5.22 -73.981720 40.736668 1 N -73.981636 40.670242 1 22.0 0.5 0.5 4.00 0.0 0.3 27.30 
2 2 2016-06-09 21:06:36 2016-06-09 21:13:10 1 1.26 -73.994316 40.751072 1 N -74.004234 40.742168 1 6.5 0.5 0.5 1.56 0.0 0.3 9.36 
3 2 2016-06-09 21:06:36 2016-06-09 21:36:10 1 7.39 -73.982361 40.773891 1 N -73.929466 40.851540 1 26.0 0.5 0.5 1.00 0.0 0.3 28.30 
4 2 2016-06-09 21:06:36 2016-06-09 21:23:23 1 3.10 -73.987106 40.733173 1 N -73.985909 40.766445 1 13.5 0.5 0.5 2.96 0.0 0.3 17.76 

このデータセットは、「ビッグデータ」ではありません11135470行を、持っていますが、小規模ではありません。関数を記述してすべての行に適用するのではなく、関数の一部を個々の列に実行することで、より多くのパフォーマンスを得ることができます。あなたはその後、計算値とpickup_eastingpickup_northing列を持っている

SEMIMAJORAXIS = 6378137.0 # typed in all caps since this is a static value 
df['pickup_east'] = df['pickup_longitude'] * 0.017453292519943295 # takes all pickup longitude values, multiples them, then saves as a new column named pickup_east. 
df['pickup_north'] = df['pickup_latitude'] * 0.017453292519943295 
# numpy functions allow you to calculate an entire column's worth of values by simply passing in the column. 
df['pickup_northing'] = 3189068.5 * np.log((1.0 + np.sin(df['pickup_north']))/(1.0 - np.sin(df['pickup_north']))) 
df['pickup_easting'] = SEMIMAJORAXIS * df['pickup_east'] 

:この中

def toWebMercator(xLon, yLat): 
    # Check if coordinate out of range for Latitude/Longitude 
    if (abs(xLon) > 180) and (abs(yLat) > 90): 
     return 

    semimajorAxis = 6378137.0 # WGS84 spheriod semimajor axis 
    east = xLon * 0.017453292519943295 
    north = yLat * 0.017453292519943295 

    northing = 3189068.5 * math.log((1.0 + math.sin(north))/(1.0 - math.sin(north))) 
    easting = semimajorAxis * east 

    return [easting, northing] 

:私は、この機能をオンにします。

私のラップトップでは、これは取る:すべての11メートルの行については

CPU times: user 1.01 s, sys: 286 ms, total: 1.3 s 
Wall time: 763 ms 

。 15分 - >秒。

私はあなたのような何か行うことができます値 - にチェックを処分した:これは再び、より高速なループよりも桁違いにブールインデックスを使用しています

df = df[(df['pickup_longitude'].abs() <= 180) & (df['pickup_latitude'].abs() <= 90)] 

を。あなたが読みやすい数学関数の種類、および現在の関数の簡単な変換を維持したい場合は

+0

ありがとう、これは本当に非常に速く、とても役に立ちました。 – CFM

0

試し:データセットのサイズで

df[['longitude', 'latitude']].apply(
    lambda x: pd.Series(toWebMercator(*x), ['xLon', 'yLay']), 
    axis=1 
) 
+0

データフレームに11 mioの行があり、15分間実行しましたが、出力が生成されませんでした。しかし、潜在的なアプローチは今私には明らかです、ありがとうございます。 – CFM

0

eval使用:

df.eval(""" 
northing = 3189068.5 * log((1.0 + sin(latitude * 0.017453292519943295))/(1.0 - sin(latitude * 0.017453292519943295))) 
easting = 6378137.0 * longitude * 0.017453292519943295""", inplace=False) 
Out[51]: 
     id longitude latitude  northing  easting 
0 11135465 -73.986893 40.761093 4.977167e+06 -8.236183e+06 
1 1113546 -73.979645 40.747814 4.975215e+06 -8.235376e+06 
2 11135467 -74.001244 40.743172 4.974533e+06 -8.237781e+06 
3 11135468 -73.997818 40.726055 4.972018e+06 -8.237399e+06 

はあなたがifを使用することはできませんのような構文に少し作業する必要がありますステートメントがありますが、evalを呼び出す前に、範囲外のデータを簡単に除外できます。新しい列を直接割り当てる場合は、inplace=Trueを使用することもできます。

もしあなたが数学の構文を保つのに興味がなく、フルスピードを探しているのであれば、numpyの答えがもっと速くなるでしょう。

関連する問題