2016-03-24 5 views
1

ich einige Code geschrieben, dass der Abstand zwischen GPS findet auf Maschinen basierend Koordinaten suchen die gleichen Seriennummern, die beiPython: Code vereinfachen, indem sie in einer Pandas spezifische Art und Weise zu schreiben

Aber ich glaube, es wird effizienter sein, wenn es vereinfacht werden kann, iterrows oder df.apply zu verwenden; aber ich kann es nicht herausfinden.

Da ich nur die Funktion ausführen muss, wenn ser_no[i] == ser_no[i+1] und einen NaN Wert an der Stelle einfügen, wo die ser_no ändert, kann ich nicht scheinen, die Pandas-Methode anzuwenden, um den Code effizienter zu machen. Ich habe betrachtet:

Leider sehe ich nicht ohne weiteres den Sprung ich auch über diese Stellen nach der Suche zu machen brauchen.

Was ich habe:

def haversine(lat1, long1, lat2, long2): 
    r = 6371 # radius of Earth in km 
    # convert decimals to degrees 
    lat1, long1, lat2, long2 = map(np.radians, [lat1, long1, lat2, long2]) 
    # haversine formula 
    lat = lat2 - lat1 
    lon = long2 - long1 
    a = np.sin(lat/2)**2 + np.cos(lat1)*np.cos(lat2)*np.sin(lon/2)**2 
    c = 2*np.arcsin(np.sqrt(a)) 
    d = r*c 
    return d 
# pre-allocate vector  
hdist = np.zeros(len(mttt_pings.index), dtype = float)  
# haversine loop calculation 
for i in range(0, len(mttt_pings.index) - 1): 
    ''' 
    when the ser_no from i and i + 1 are the same calculate the distance 
    between them using the haversine formula and put the distance in the 
    i + 1 location 
    ''' 
    if mttt_pings.ser_no.loc[i] == mttt_pings.ser_no[i + 1]: 
     hdist[i + 1] = haversine(mttt_pings.EQP_GPS_SPEC_LAT_CORD[i], \ 
     mttt_pings.EQP_GPS_SPEC_LONG_CORD[i], \ 
     mttt_pings.EQP_GPS_SPEC_LAT_CORD[i + 1], \ 
     mttt_pings.EQP_GPS_SPEC_LONG_CORD[i + 1]) 
    else: 
     hdist = np.insert(hdist, i, np.nan) 
    ''' 
    when ser_no i and i + 1 are not the same, insert NaN at the ith location 
    ''' 
+0

Können Sie ein Beispiel Ihrer Daten veröffentlichen? – AGS

Antwort

1

Die Hauptidee ist shift zu verwenden aufeinanderfolgende Zeilen zu überprüfen. Ich schreibe auch eine get_dist Funktion nur umschließt Ihre vorhandene Distanz-Funktion, um Dinge lesbarer zu machen, wenn ich apply verwenden, um Entfernungen zu berechnen.

def get_dist(row): 
    lat1 = row['EQP_GPS_SPEC_LAT_CORD'] 
    long1 = row['EQP_GPS_SPEC_LONG_CORD'] 
    lat2 = row['EQP_GPS_SPEC_LAT_CORD_2'] 
    long2 = row['EQP_GPS_SPEC_LONG_CORD_2'] 
    return haversine(lat1, long1, lat2, long2) 

# Find consecutive rows with matching ser_no, and get coordinates. 
coord_cols = ['EQP_GPS_SPEC_LAT_CORD', 'EQP_GPS_SPEC_LONG_CORD'] 
matching_ser = mttt_pings['ser_no'] == mttt_pings['ser_no'].shift(1) 
shift_coords = mttt_pings.shift(1).loc[matching_ser, coord_cols] 

# Join shifted coordinates and compute distances. 
mttt_pings_shift = mttt_pings.join(shift_coords, how='inner', rsuffix='_2') 
mttt_pings['hdist'] = mttt_pings_shift.apply(get_dist, axis=1) 

Im obigen Code habe ich die Abstände zu Ihrem Dataframe hinzugefügt. Wenn Sie das Ergebnis als numpy Array erhalten möchten, können Sie tun:

hdist = mttt_pings['hdist'].values 

Als Randbemerkung, können Sie mit geopy.distance.vincenty betrachten Abstände zwischen lat/long-Koordinaten zu berechnen. Im Allgemeinen ist vincenty genauer als haversine, obwohl die Berechnung länger dauern kann. Für die Verwendung von vincenty sind nur geringfügige Änderungen an der get_dist-Funktion erforderlich.

from geopy.distance import vincenty 

def get_dist(row): 
    lat1 = row['EQP_GPS_SPEC_LAT_CORD'] 
    long1 = row['EQP_GPS_SPEC_LONG_CORD'] 
    lat2 = row['EQP_GPS_SPEC_LAT_CORD_2'] 
    long2 = row['EQP_GPS_SPEC_LONG_CORD_2'] 
    return vincenty((lat1, long1), (lat2, long2)).km 
Verwandte Themen