У меня есть этот фрейм данных:
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'
и так далее. Итак, как я могу присвоить город более приемлемым образом с использованием значений широты и долготы?
Фрагмент кода, который вы используете, был с 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