Присвоение названия города значениями широты / долготы в кадре данных Pandas

1

У меня есть этот фрейм данных:

    userId      latitude    longitude        dateTime
0   121165      30.314368   76.384381   2018-02-01 00:01:57
1   95592       13.186810   77.643769   2018-02-01 00:02:17
2   111435      28.512889   77.088154   2018-02-01 00:04:02
3   129532      9.828420    76.310357   2018-02-01 00:06:03
4   95592       13.121986   77.610539   2018-02-01 00:08:54

Я хочу создать новый столбец dataframe, например:

     userId  latitude   longitude    dateTime              city
0   121165  30.314368   76.384381   2018-02-01   00:01:57  Bengaluru
1   95592   13.186810   77.643769   2018-02-01   00:02:17  Delhi
2   111435  28.512889   77.088154   2018-02-01   00:04:02  Mumbai
3   129532  9.828420    76.310357   2018-02-01   00:06:03  Chennai
4   95592   13.121986   77.610539   2018-02-01   00:08:54  Delhi

Я видел этот код здесь, но он не работает.

Это код:

from urllib2 import urlopen
import json
def getplace(lat, lon):
    url = "http://maps.googleapis.com/maps/api/geocode/json?"
    url += "latlng=%s,%s&sensor=false" % (lat, lon)
    v = urlopen(url).read()
    j = json.loads(v)
    components = j['results'][0]['address_components']
    country = town = None
    for c in components:
        if "country" in c['types']:
            country = c['long_name']
        if "postal_town" in c['types']:
            town = c['long_name']
    return town, country
for i,j in df['latitude'], df['longitude']:
    getplace(i, j)

Я получаю ошибку в этом месте:

components = j['results'][0]['address_components']

индекс списка вне диапазона

Я добавил некоторые другие значения долготы широты в Великобритании, и это сработало, но не для индийских штатов.

Итак, теперь я хочу попробовать что-то вроде этого:

if i,j in zip(range(79,80),range(83,84)):
    df['City']='Bengaluru'
elif i,j in zip(range(13,14),range(70,71)):
    df['City']='Delhi'

и так далее. Итак, как я могу присвоить город более приемлемым образом с использованием значений широты и долготы?

Теги:
pandas
dataframe
numpy
google-maps

1 ответ

0
Лучший ответ

Фрагмент кода, который вы используете, был с 2013 года; API Google изменился, и 'postal_town' больше не доступен.

Вы можете использовать следующий код, который использует библиотеку requests и помещает охрану в случае отсутствия возвращаемых результатов.

In [48]: def location(lat, long):
    ...:     url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng={0},{1}&sensor=false'.format(lat, long)
    ...:     r = requests.get(url)
    ...:     r_json = r.json()
    ...:     if len(r_json['results']) < 1: return None, None
    ...:     res = r_json['results'][0]['address_components']
    ...:     country  = next((c['long_name'] for c in res if 'country' in c['types']), None)
    ...:     locality = next((c['long_name'] for c in res if 'locality' in c['types']), None)
    ...:     return locality, country
    ...:

In [49]: location(28.512889, 77.088154)
Out[49]: ('Gurugram', 'India')

Эта функция выполняет поиск 'locality' и фактически ничего не возвращает для второй строки DataFrame. Вы можете выбрать, какие поля вы хотите 30.314368, 76.384381 результаты (это с lat, long значение 30.314368, 76.384381)

[{'long_name': 'Udyog Vihar',
  'short_name': 'Udyog Vihar',
  'types': ['political', 'sublocality', 'sublocality_level_2']},
 {'long_name': 'Kapas Hera Estate',
  'short_name': 'Kapas Hera Estate',
  'types': ['political', 'sublocality', 'sublocality_level_1']},
 {'long_name': 'Gurugram',
  'short_name': 'Gurugram',
  'types': ['locality', 'political']},
 {'long_name': 'Gurgaon',
  'short_name': 'Gurgaon',
  'types': ['administrative_area_level_2', 'political']},
 {'long_name': 'Haryana',
  'short_name': 'HR',
  'types': ['administrative_area_level_1', 'political']},
 {'long_name': 'India', 'short_name': 'IN', 'types': ['country', 'political']},
 {'long_name': '122016', 'short_name': '122016', 'types': ['postal_code']}]

Чтобы применить это к вашему DataFrame, вы можете использовать numpy vectorize следующим образом (помните, что вторая строка ничего не вернет)

In [71]: import numpy as np

In [72]: df['locality'] = np.vectorize(location)(df['latitude'], df['longitude'])

In [73]: df
Out[73]:
   userId   latitude  longitude             dateTime   locality
0  121165  30.314368  76.384381  2018-02-01 00:01:57    Patiala
1   95592  13.186810  77.643769  2018-02-01 00:02:17       None
2  111435  28.512889  77.088154  2018-02-01 00:04:02   Gurugram
3  129532   9.828420  76.310357  2018-02-01 00:06:03  Ezhupunna
4   95592  13.121986  77.610539  2018-02-01 00:08:54  Bengaluru

PS Я отметил, что местонахождение города желаемого результата неверно.

PPS Вы также должны заметить, что это может занять некоторое время, поскольку функция должна каждый раз запрашивать API

Вы также можете создать функцию определения местоположения с более широкими диапазонами, но она будет очень грубой, и вы можете покрыть слишком широкую область. Затем вы можете использовать функцию так же, как показано ранее

In [21]: def location(lat, long):
    ...:     if 9 <= lat < 10 and 76 <= long < 77:
    ...:         return 'Chennai'
    ...:     elif 13 <= lat < 14 and 77 <= long < 78:
    ...:         return 'Dehli'
    ...:     elif 28 <= lat < 29 and 77 <= long < 78:
    ...:         return 'Mumbai'
    ...:     elif 30 <= lat < 31 and 76 <= long < 77:
    ...:         return 'Bengaluru'
    ...:     

In [22]: df['city'] = np.vectorize(location)(df['latitude'], df['longitude'])

In [23]: df
Out[23]: 
   userId   latitude  longitude             dateTime       city
0  121165  30.314368  76.384381  2018-02-01 00:01:57  Bengaluru
1   95592  13.186810  77.643769  2018-02-01 00:02:17      Dehli
2  111435  28.512889  77.088154  2018-02-01 00:04:02     Mumbai
3  129532   9.828420  76.310357  2018-02-01 00:06:03    Chennai
4   95592  13.121986  77.610539  2018-02-01 00:08:54      Dehli
  • 0
    Это занимает слишком много времени. очень долгое время.
  • 0
    насколько велика ваша датафрейм?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню