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]()
Ответы
Ответ 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])