JSON для pandas DataFrame - программирование
Подтвердить что ты не робот

JSON для pandas DataFrame

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

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 headers).

Если кто-то может помочь или дать совет по работе с этими данными, это было бы здорово! Если вы не можете сказать, что я не много работал с данными 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

4b9b3361

Ответ 1

Я нашел быстрое и простое решение того, что мне нужно, используя функцию 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'])

Это дает хороший сплющенный фрейм данных с данными json, которые я получил из API карт google.

Ответ 2

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

# 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)

Надеюсь, это поможет:)

Ответ 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']

Перестроить строку json:

elevations = json.dumps(data)

Наконец:

pd.read_json(elevations)

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

Ответ 4

Проблема заключается в том, что у вас есть несколько столбцов в фрейме данных, которые содержат 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')

Ответ 5

Решение billmanH помогло мне, но не работало, пока я не переключился с:

n = data.loc[row,'json_column']

чтобы:

n = data.iloc[[row]]['json_column']

здесь, в остальном, преобразование в словарь полезно для работы с данными JSON.

import json

for row in range(len(data)):
    n = data.iloc[[row]]['json_column'].item()
    jsonDict = json.loads(n)
    if ('mykey' in jsonDict):
        display(jsonDict['mykey'])

Ответ 6

Просто новая версия принятого ответа, так как python3.x не поддерживает urllib2

from requests import request
import json
from pandas.io.json import json_normalize

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

Ответ 7

#Use the small trick to make the data json interpret-able
#Since your data is not directly interpreted by json.loads()

>>> import json
>>> f=open("sampledata.txt","r+")
>>> data = f.read()
>>> for x in data.split("\n"):
...     strlist = "["+x+"]"
...     datalist=json.loads(strlist)
...     for y in datalist:
...             print(type(y))
...             print(y)
...
...
<type 'dict'>
{u'0': [[10.8, 36.0], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'1': [[10.8, 36.1], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'2': [[10.8, 36.2], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'3': [[10.8, 36.300000000000004], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'4': [[10.8, 36.4], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'5': [[10.8, 36.5], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'6': [[10.8, 36.6], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'7': [[10.8, 36.7], {u'10': 0, u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'8': [[10.8, 36.800000000000004], {u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}
<type 'dict'>
{u'9': [[10.8, 36.9], {u'1': 0, u'0': 0, u'3': 0, u'2': 0, u'5': 0, u'4': 0, u'7': 0, u'6': 0, u'9': 0, u'8': 0}]}


Ответ 8

Вот небольшой вспомогательный класс, который преобразует JSON в DataFrame и обратно: Надеюсь, вы найдете это полезным.

# -*- coding: utf-8 -*-
from pandas.io.json import json_normalize

class DFConverter:

    #Converts the input JSON to a DataFrame
    def convertToDF(self,dfJSON):
        return(json_normalize(dfJSON))

    #Converts the input DataFrame to JSON 
    def convertToJSON(self, df):
        resultJSON = df.to_json(orient='records')
        return(resultJSON)

Ответ 9

Как только вы получите плоский DataFrame полученный по принятому ответу, вы можете сделать столбцы MultiIndex ("причудливый многострочный заголовок") следующим образом:

df.columns = pd.MultiIndex.from_tuples([tuple(c.split('.')) for c in df.columns])