2017-10-14 12 views
1

Première fois l'affichage sur StackOverflow, donc avec moi portent si je fais quelques faux pas :) Veuillezapplication d'une fonction lambda pour pandas géants dataframe

Je suis en train de calculer la distance entre deux points, en utilisant geopy, mais je ne peux pas vraiment faire fonctionner l'application réelle du calcul.

est ici la tête du dataframe je travaille avec (il y a quelques valeurs manquantes plus tard dans la trame de données, pas sûr si cela est le problème ou la façon de le traiter en général):

start lat start long end_lat end_long 
0 38.902760 -77.038630 38.880300 -76.986200 
2 38.895914 -77.026064 38.915400 -77.044600 
3 38.888251 -77.049426 38.895914 -77.026064 
4 38.892300 -77.043600 38.888251 -77.049426 

I ai mis en place une fonction:

def dist_calc(st_lat, st_long, fin_lat, fin_long): 
    from geopy.distance import vincenty 
    start = (st_lat, st_long) 
    end = (fin_lat, fin_long) 
    return vincenty(start, end).miles 

celui-ci fonctionne très bien quand donné la saisie manuelle.

Cependant, lorsque je tente d'appliquer() la fonction, je rencontre des problèmes avec le code ci-dessous:

distances = df.apply(lambda row: dist_calc(row[-4], row[-3], row[-2], row[-1]), axis=1) 

Je suis assez nouveau pour python, toute aide sera très appréciée!

Edit: message d'erreur:

distances = df.apply(lambda row: dist_calc2(row[-4], row[-3], row[-2], row[-1]), axis=1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/frame.py", line 4262, in apply 
    ignore_failures=ignore_failures) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/frame.py", line 4358, in _apply_standard 
    results[i] = func(v) 
    File "<stdin>", line 1, in <lambda> 
    File "<stdin>", line 5, in dist_calc2 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/geopy/distance.py", line 322, in __init__ 
    super(vincenty, self).__init__(*args, **kwargs) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/geopy/distance.py", line 115, in __init__ 
    kilometers += self.measure(a, b) 
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/geopy/distance.py", line 414, in measure 
    u_sq = cos_sq_alpha * (major ** 2 - minor ** 2)/minor ** 2 
UnboundLocalError: ("local variable 'cos_sq_alpha' referenced before assignment", 'occurred at index 10') 
+0

Si je copie vos données et exécuter votre code, cela fonctionne. Quelque chose doit être différent de vos données et/ou du code. Aussi, pourquoi ne partagez-vous pas les problèmes que vous rencontrez? Lisez également [** MCVE **] (http://stackoverflow.com/help/mcve). Cela nous aidera à vous aider. – piRSquared

+0

"J'ai des ennuis"? Quel problème??? Qu'est-ce qui possède des gens pour afficher un tel flou? –

+0

@Ribzy, quel est le message d'erreur que vous obtenez? – MedAli

Répondre

1

Les paramètres par défaut des fonctions de pandas généralement utilisées pour importer des données de texte comme celui-ci (pd.read_table(), etc.) interprétera les espaces dans les 2 premiers noms de colonnes comme séparateurs , vous vous retrouverez avec 6 colonnes au lieu de 4, et vos données seront Désalignement:

In [23]: df = pd.read_clipboard() 

In [24]: df 
Out[24]: 
    start  lat start.1  long end_lat end_long 
0  0 38.902760 -77.038630 38.880300 -76.986200  NaN 
1  2 38.895914 -77.026064 38.915400 -77.044600  NaN 
2  3 38.888251 -77.049426 38.895914 -77.026064  NaN 
3  4 38.892300 -77.043600 38.888251 -77.049426  NaN 

In [25]: df.columns 
Out[25]: Index(['start', 'lat', 'start.1', 'long', 'end_lat', 'end_long'], dtype='object') 

noms de colonnes d'avis sont fausses, la dernière colonne est pleine de Nans, etc. Si je demande que votre fonction l'image de données dans ce formulaire, je reçois la même erreur que vous avez fait.

Il est généralement préférable d'essayer de résoudre ce problème avant de l'importer en tant que données. Je peux penser à 2 méthodes:

  1. nettoyer les données avant l'importation, par exemple le copier dans un éditeur et remplacer les espaces fautifs par des traits de soulignement. C'est le plus facile.
  2. utilisez une regex pour le réparer pendant l'importation. Cela peut être nécessaire si l'ensemble de données est très volumineux ou s'il provient d'un site Web et doit être actualisé régulièrement.

Voici un exemple de cas (2):

In [35]: df = pd.read_clipboard(sep=r'\s{2,}|\s(?=-)', engine='python') 

In [36]: df = df.rename_axis({'start lat': 'start_lat', 'start long': 'start_long'}, axis=1) 

In [37]: df 
Out[37]: 
    start_lat start_long end_lat end_long 
0 38.902760 -77.038630 38.880300 -76.986200 
2 38.895914 -77.026064 38.915400 -77.044600 
3 38.888251 -77.049426 38.895914 -77.026064 
4 38.892300 -77.043600 38.888251 -77.049426 

Les séparateurs précisé que doivent contenir soit 2+ caractères ou espaces blancs 1 blanc suivi d'un tiret (signe moins). Ensuite, je renommer les colonnes à ce que je suppose sont les valeurs attendues.

De ce point votre fonction/application fonctionne très bien, mais je l'ai changé un peu:

  • pep8 recommande de mettre les importations en haut de chaque fichier, plutôt que dans une fonction
  • l'extraction colonnes par nom est plus robuste, et aurait donné une erreur beaucoup plus compréhensible que l'erreur étrange levée par geopy.

Par exemple:

In [51]: def dist_calc(row): 
    ...: start = row[['start_lat','start_long']] 
    ...: end = row[['end_lat', 'end_long']] 
    ...: return vincenty(start, end).miles 
    ...: 

In [52]: df.apply(lambda row: dist_calc(row), axis=1) 
Out[52]: 
0 3.223232 
2 1.674780 
3 1.365851 
4 0.420305 
dtype: float64 
+0

Merci beaucoup. Cela m'a aidé à me trouver à la fin. Il lance la même erreur lorsqu'il est exposé à NaN. Alors devra mettre dans une disposition pour cela. – Ribzy