JSON - Pandalar DataFrame


144

Ne yapmaya çalışıyorum aşağıdaki gibi enlem ve boylam koordinatları tarafından belirtilen bir yol boyunca bir google haritalar API yükseklik verileri ayıklamak olduğunu:

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

Bu bana şöyle bir veri veriyor:

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"',
 '}']

burada DataFrame olarak koyarak ne olsun:

resim açıklamasını buraya girin

pd.read_json(elevations)

ve işte istediğim şey:

resim açıklamasını buraya girin

Bunun mümkün olup olmadığından emin değilim, ancak esas olarak aradığım şey, yükseklik, enlem ve boylam verilerini bir panda veri çerçevesinde bir araya getirmenin bir yoludur (fantezi mutiline başlıkları olması gerekmez).

Herhangi biri bu verilerle çalışma konusunda yardımcı olabilir veya tavsiyede bulunabilseydi, bu harika olurdu! Daha önce json verileriyle fazla çalışmadığımı söyleyemiyorsanız ...

DÜZENLE:

Bu yöntem o kadar çekici değil ama işe yarıyor gibi görünüyor:

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

enlem, boylam, yükseklik sütunlarına sahip veri çerçevesini sonlandırır

resim açıklamasını buraya girin


Merhaba arkadaşım, nasıl json parçası alabilirim biliyor musun? bazı alt bölüm?
M. Mariscal

Yanıtlar:


185

Ben kullanarak istediğini için hızlı ve kolay bir çözüm buldu json_normalize()dahil pandas 1.01.

from urllib2 import Request, urlopen
import json

import pandas as pd    

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)
df = pd.json_normalize(data['results'])

Bu, Google Haritalar API'sından aldığım json verileriyle hoş bir düzleştirilmiş veri çerçevesi sağlar.


13
Bu artık işe yaramıyor gibi görünüyor - pd.DataFrame.from_records()Burada açıklandığı gibi kullanmak zorunda kaldım stackoverflow.com/a/33020669/1137803
avv

4
from_records zaman zaman json yeterince karmaşıksa da çalışmaz, bir flatmap almak için json.io.json.json_normalize uygulamanız gerekir stackoverflow.com/questions/39899005/…
devssh

27

Bu alıntıyı kontrol et.

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

Umarım yardımcı olur :)


1
Hata. Dosya içeriğini (yani bir dize) dosya nesnesinin kendisini değil, json.loads () öğesine iletmelisiniz - json.load (train_file.read ())
Vasin Yuriy

13

Önce json verilerinizi bir Python sözlüğüne aktarabilirsiniz:

data = json.loads(elevations)

Ardından verileri anında değiştirin:

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 dizesini yeniden oluştur:

elevations = json.dumps(data)

En sonunda :

pd.read_json(elevations)

Ayrıca, muhtemelen bir dizeye veri dökümünden kaçınabilirsiniz, Panda'nın doğrudan bir sözlükten bir DataFrame oluşturabileceğini varsayıyorum (uzun zamandır kullanmadım: p)


Yine json verilerini ve oluşturulan sözlüğü kullanarak aynı sonucu elde ediyorum. Veri çerçevesindeki her öğenin kendine göre bir diktesi var gibi görünüyor. Yaklaşımınızı daha az çekici bir şekilde kullanarak 'veri' üzerinden yineleme yaparken lat, lng ve yükseklik için ayrı bir liste oluşturmayı denedim.
pbreach

@ user2593236: Merhaba, SO kodumu kopyalarken / yapıştırırken bir hata yaptım: bir del eksik (cevap düzenlendi)
Raphaël Braud

Hmm .. Json verilerinin geri kalanı her hücrede dikte olarak görünürken, üstbilgi olarak 'sonuç' ve 'durum' olduğu şeyle aynı. Bu sorunun çözümünün veri formatını 'sonuçlar' ve 'durum' olarak alt bölümlere ayrılmayacak şekilde değiştirmek olacağını düşünüyorum, o zaman veri çerçevesi 'lat', 'lng', 'yükseklik', ' çözünürlüğü 'ayrı başlıklar olarak. Ya bu, ya da ben soruda belirttiğim gibi çok düzeyli bir başlık dizini olacak bir veri çerçevesine json veri yüklemek için bir yol bulmak gerekir.
pbreach

Hangi final masasını bekliyorsunuz? Düzenlemenizden sonra aldığınız?
Raphaël Braud

Son düzenlememden sonra aldığım iş, temelde ihtiyacım olan tüm verileri dışa aktarabileceğim ve çalışabileceğim tablo biçiminde elde
etmekti

9

Kabul python3.xetmediği gibi, kabul edilen cevabın sadece yeni bir versiyonuurllib2

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'])

4

Sorun, veri çerçevesi içinde, içinde daha küçük diktleri olan diktler içeren birkaç sütunun olmasıdır. Yararlı Json genellikle iç içe geçer. İstediğim bilgiyi yeni bir sütuna çeken küçük fonksiyonlar yazıyorum. Bu şekilde kullanmak istediğim formatta var.

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

4

Kabul edilen cevabın optimizasyonu:

Kabul edilen cevabın bazı işlevsel sorunları var, bu yüzden urllib2'ye dayanmayan kodumu paylaşmak istiyorum:

import requests
from pandas.io.json import json_normalize
url = 'https://www.energidataservice.dk/proxy/api/datastore_search?resource_id=nordpoolmarket&limit=5'

r = requests.get(url)
dictr = r.json()
recs = dictr['result']['records']
df = json_normalize(recs)
print(df)

Çıktı:

        _id                    HourUTC               HourDK  ... ElbasAveragePriceEUR  ElbasMaxPriceEUR  ElbasMinPriceEUR
0    264028  2019-01-01T00:00:00+00:00  2019-01-01T01:00:00  ...                  NaN               NaN               NaN
1    138428  2017-09-03T15:00:00+00:00  2017-09-03T17:00:00  ...                33.28              33.4              32.0
2    138429  2017-09-03T16:00:00+00:00  2017-09-03T18:00:00  ...                35.20              35.7              34.9
3    138430  2017-09-03T17:00:00+00:00  2017-09-03T19:00:00  ...                37.50              37.8              37.3
4    138431  2017-09-03T18:00:00+00:00  2017-09-03T20:00:00  ...                39.65              42.9              35.3
..      ...                        ...                  ...  ...                  ...               ...               ...
995  139290  2017-10-09T13:00:00+00:00  2017-10-09T15:00:00  ...                38.40              38.4              38.4
996  139291  2017-10-09T14:00:00+00:00  2017-10-09T16:00:00  ...                41.90              44.3              33.9
997  139292  2017-10-09T15:00:00+00:00  2017-10-09T17:00:00  ...                46.26              49.5              41.4
998  139293  2017-10-09T16:00:00+00:00  2017-10-09T18:00:00  ...                56.22              58.5              49.1
999  139294  2017-10-09T17:00:00+00:00  2017-10-09T19:00:00  ...                56.71              65.4              42.2 

PS: API Danimarka elektrik fiyatları içindir


3

İşte JSON DataFrame ve geri dönüştüren küçük yarar sınıfı: Umarım bu yararlı bulabilirsiniz.

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

1

billmanH'ın çözümü bana yardımcı oldu, ancak geçiş yapana kadar çalışmadı:

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

için:

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

işte geri kalanı, bir sözlüğe dönüştürmek json verileri ile çalışmak için yararlıdır.

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'])

1
#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}]}


1

DataFrameKabul edilen yanıtı elde ettiğinizde düzleştirdikten sonra , sütunları aşağıdaki gibi bir MultiIndex("süslü çok satırlı başlık") yapabilirsiniz:

df.columns = pd.MultiIndex.from_tuples([tuple(c.split('.')) for c in df.columns])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.