2016-10-18 2 views
0

Ich habe einen Datenrahmen wie folgt aus:Pandas Dataframe Spalten Algorithmus tun

df = pd.DataFrame({ 
    'A': ['a', 'a', 'a', 'a', 'a'], 
    'lon1': [128.0, 135.0, 125.0, 123.0, 136.0], 
    'lon2': [128.0, 135.0, 139.0, 142.0, 121.0], 
    'lat1': [38.0, 32.0, 38.0, 38.0, 38.0], 
    'lat2': [31.0, 32.0, 35.0, 38.0, 29.0], 
    'angle': [0, 0, 0, 0, 0] 
}) 

Ich möchte von dieser Funktion den Winkel jeder Zeile zählen und zurück in die Winkel Spalte

def angle(lon1,lat1,lon2,lat2): 
    dx = lon2 - lon1 
    dy = lat2 - lat1 
    direction = 0; 
    if ((dx == 0) & (dy == 0)): # same position 
    return direction 
    if (dx > 0.0) :  
     direction = 90-np.arctan2(dy,dx)*180/np.pi 
    elif (dy > 0.0) :  
     direction = 180+(270-(np.arctan2(dy,dx)*180/np.pi)) 
    else : 
     direction = 360-(270+(np.arctan2(dy,dx)*180/np.pi)) 
     if (direction < 0) : 
      direction += 360 

    return (direction.astype(int) % 360) 

Ich habe versucht, speichern

df.ix[df['A'].notnull(), 'angle'] =angle(
    df[df['A'].notnull()]['lon1'], 
    df[df['A'].notnull()]['lat1'], 
    df[df['A'].notnull()]['lon2'], 
    df[df['A'].notnull()]['lat2']) 

und ich habe einen Fehler

Ich versuchte for index,row in df.iterrows(): das Ergebnis der for-Schleife ist ok, aber es dauerte furchtbar lange, lange Zeit (Originaldaten ca. 10 Millionen Zeilen)

könnte jemand freundlicherweise einige effiziente Methoden geben?

+0

Meinst du, dass alle Werte im df Strings sind oder war das ein Fehler? – shawnheide

+0

nur Spalte ['A'] ist Objekt andere sind float – user2775128

+0

Vectorisieren Sie Ihren Algorithmus: Sie denken über Ihre Berechnung mit einer prozeduralen Denkweise nach, also schreiben Sie eine Prozedur. Sie müssen in Vektoren denken, und anstatt eine Funktion zu schreiben, erhalten Sie tatsächlichen Code gegen den Datenrahmen, der ausgeführt werden soll. – Boud

Antwort

1

Es scheint, als ob Sie versuchen, die Funktion angle(...) auf jede Zeile Ihres Datenrahmens anzuwenden.

Zuerst müssen Sie alle Ihre string-typed Zahlen in float umwandeln, um zu berechnen.

df1.loc[:, "lon1"] = df1.loc[:, "lon1"].astype("float") 
df1.loc[:, "lon2"] = df1.loc[:, "lon2"].astype("float") 
df1.loc[:, "lat1"] = df1.loc[:, "lat2"].astype("float") 
df1.loc[:, "lat2"] = df1.loc[:, "lat2"].astype("float") 

Dort gehen Sie.

df1.loc[:, "angle"] = df1.apply(lambda x: angle(x["lon1"], x["lat1"], x["lon2"], x["lat2"]), axis = 1) 

Zur Leistungsbeeinträchtigung, hier sind einige Tipps für Sie.

  1. Profilierung.
  2. Verwenden Sie numba für JIT-Kompilierung und automatische Vektorisierung Ihrer Funktion.
+0

es ist hilfreich! Danke ! – user2775128

0

Ich bin sicher, es gibt eine mehr vektorisiert Lösung, aber hier ist eine Lösung, die reihenweise Version der apply Methode, die nur leicht Ihre Funktion ändert:

def angle(row): 
    dx = row.lon2 - row.lon1 
    dy = row.lat2 - row.lat1 
    direction = 0; 
    if ((dx == 0) & (dy == 0)): # same position 
     return direction 
    if (dx > 0.0) :  
     direction = 90-np.arctan2(dy,dx)*180/np.pi 
    elif (dy > 0.0) :  
     direction = 180+(270-(np.arctan2(dy,dx)*180/np.pi)) 
    else : 
     direction = 360-(270+(np.arctan2(dy,dx)*180/np.pi)) 
    if (direction < 0) : 
     direction += 360 

    return (direction.astype(int) % 360) 

df['angle'] = df.apply(angle, axis=1) 

Ausgang:

A angle lat1 lat2 lon1 lon2 
0 a 180  38.0 31.0 128.0 128.0 
1 a 0  32.0 32.0 135.0 135.0 
2 a 102  38.0 35.0 125.0 139.0 
3 a 90  38.0 38.0 123.0 142.0 
4 a 239  38.0 29.0 136.0 121.0 
Verwandte Themen