2014-01-14 3 views
50

То, что я пытаюсь сделать, это высота извлечение данных из API Google Maps вдоль пути, указанного широты и долготы следующим образом:JSON для панды DataFrame

from urllib2 import Request, urlopen 
import json 

path1 = '42.974049,-81.205203|42.974298,-81.195755' 
request=Request('http://maps.googleapis.com/maps/api/elevation/json?locations='+path1+'&sensor=false') 
response = urlopen(request) 
elevations = response.read() 

Это дает мне данные, выглядит следующим образом :

elevations.splitlines() 

['{', 
' "results" : [', 
'  {', 
'   "elevation" : 243.3462677001953,', 
'   "location" : {', 
'   "lat" : 42.974049,', 
'   "lng" : -81.205203', 
'   },', 
'   "resolution" : 19.08790397644043', 
'  },', 
'  {', 
'   "elevation" : 244.1318664550781,', 
'   "location" : {', 
'   "lat" : 42.974298,', 
'   "lng" : -81.19575500000001', 
'   },', 
'   "resolution" : 19.08790397644043', 
'  }', 
' ],', 
' "status" : "OK"', 
'}'] 

при вводе в качестве DataFrame вот что я получаю:

enter image description here

pd.read_json(elevations) 

и вот что я хочу:

enter image description here

Я не уверен, если это возможно, но в основном то, что я ищу способ, чтобы иметь возможность поставить отметку, широта и данные о долготе вместе в рамке данных pandas (не обязательно иметь модные заголовки mutiline).

Если кто-нибудь может помочь или дать совет по работе с этими данными, это было бы здорово! Если вы не можете сказать, что я не работал много с данными JSON до ...

EDIT:

Этот метод не так привлекательно, но, кажется, работает:

data = json.loads(elevations) 
lat,lng,el = [],[],[] 
for result in data['results']: 
    lat.append(result[u'location'][u'lat']) 
    lng.append(result[u'location'][u'lng']) 
    el.append(result[u'elevation']) 
df = pd.DataFrame([lat,lng,el]).T 

концы до dataframe, имеющие столбцы широта, долгота, высота

enter image description here

ответ

70

Я нашел быстрое и простое решение того, что я хотел использовать функцию json_normalize, включенную в последнюю версию pandas 0.13.

from urllib2 import Request, urlopen 
import json 
from pandas.io.json import json_normalize 

path1 = '42.974049,-81.205203|42.974298,-81.195755' 
request=Request('http://maps.googleapis.com/maps/api/elevation/json?locations='+path1+'&sensor=false') 
response = urlopen(request) 
elevations = response.read() 
data = json.loads(elevations) 
json_normalize(data['results']) 

Это дает хороший сглаженный dataframe с данными JSON, что я получил от Google Maps API.

+3

. Это больше не работает - мне пришлось использовать 'pd.DataFrame. from_records() ', как описано здесь http://stackoverflow.com/a/33020669/1137803 – avv

3

Вы могли бы сначала импортировать данные JSON в dictionnary Python:

data = json.loads(elevations) 

Затем измените данные на лету:

for result in data['results']: 
    result[u'lat']=result[u'location'][u'lat'] 
    result[u'lng']=result[u'location'][u'lng'] 
    del result[u'location'] 

Rebuild JSon строку:

elevations = json.dumps(data) 

Наконец:

pd.read_json(elevations) 

Вы можете, также, вероятно, избежать сваливать данные возвращаются к строке, я предполагаю, что Panda может непосредственно создать DataFrame из dictionnary (я не использовал его с давних пор: p)

+0

Я до сих пор в конечный итоге с тем же результатом, используя данные JSON и словарь, который был создан. Кажется, что каждый элемент в dataframe имеет собственный dict. Я попытался использовать ваш подход менее привлекательно, создав отдельный список для lat, lng и elevation, итерации через «данные». – pbreach

+0

@ user2593236: Здравствуйте, я сделал ошибку при копировании/вставке моего кода в SO: del отсутствовал (отредактирован ответ) –

+0

Хм .. Все те же вещи, где у него есть «результаты» и «статус» в качестве заголовков, в то время как остальные из json-данных появляются как dicts в каждой ячейке. Я думаю, что решение этой проблемы состояло бы в том, чтобы изменить формат данных, чтобы он не был разделен на «результаты» и «статус», тогда кадр данных будет использовать «lat», «lng», «elevation», разрешение "в виде отдельных заголовков. Либо это, либо мне нужно будет найти способ загрузки json-данных в фреймворк данных, который будет иметь многоуровневый индекс заголовка, как я упоминал в вопросе. – pbreach

1

Проблема заключается в том, что у вас есть несколько столбцов в фрейме данных, которые содержат dicts с меньшими dicts внутри них. Полезный Json часто сильно вложен. Я писал небольшие функции, которые вытаскивают информацию, которую я хочу, в новый столбец. Таким образом, у меня есть это в формате, который я хочу использовать.

for row in range(len(data)): 
    #First I load the dict (one at a time) 
    n = data.loc[row,'dict_column'] 
    #Now I make a new column that pulls out the data that I want. 
    data.loc[row,'new_column'] = n.get('key') 
7

Проверьте этот снимок.

# reading the JSON data using json.load() 
file = 'data.json' 
with open(file) as train_file: 
    dict_train = json.load(train_file) 

# converting json dataset from dictionary to dataframe 
train = pd.DataFrame.from_dict(dict_train, orient='index') 
train.reset_index(level=0, inplace=True) 

Надеется, что это помогает :)

Смежные вопросы