JSON에서 팬더로 DataFrame


144

내가하려는 것은 다음과 같이 위도 및 경도 좌표로 지정된 경로를 따라 Google Maps API에서 고도 데이터를 추출하는 것입니다.

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으로 넣을 때 여기에 내가 얻는 것이 있습니다.

여기에 이미지 설명을 입력하십시오

pd.read_json(elevations)

그리고 여기 내가 원하는 것입니다 :

여기에 이미지 설명을 입력하십시오

이것이 가능한지 확실하지 않지만 주로 내가 찾고있는 것은 판다 데이터 프레임에 고도, 위도 및 경도 데이터를 함께 넣을 수있는 방법입니다 (멋진 mutiline 헤더가 필요하지 않음).

이 데이터로 작업하는 데 도움이되거나 조언을 해줄 수 있다면 좋을 것입니다! 이전에 json 데이터를 많이 사용하지 않았다고 말할 수 없다면 ...

편집하다:

이 방법은 그다지 매력적이지는 않지만 작동하는 것 같습니다.

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

열 위도, 경도, 고도를 가진 데이터 프레임을 종료합니다.

여기에 이미지 설명을 입력하십시오


안녕하세요 친구, 당신은 JSON 조각을 얻는 방법을 알고 있습니까? 일부 하위?
M. Mariscal

답변:


185

json_normalize()포함 하여 사용하려는 것에 대한 빠르고 쉬운 솔루션을 찾았 습니다 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'])

이것은 Google Maps API에서 얻은 json 데이터가 포함 된 멋진 데이터 프레임을 제공합니다.


13
더 이상 작동하지 않는 것 같습니다. pd.DataFrame.from_records()여기 설명 된대로 사용해야 했습니다. stackoverflow.com/a/33020669/1137803
avv

4
json이 충분히 복잡한 경우 from_records도 때때로 작동하지 않습니다. 평면 맵을 얻으려면 json.io.json.json_normalize를 적용해야합니다. stackoverflow.com/questions/39899005/…
devssh

27

이 조각을 확인하십시오.

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

그것이 도움이되기를 바랍니다 :)


1
오류. 파일 내용 자체가 아닌 json.loads ()에 파일 내용 (예 : 문자열)을 전달해야합니다.-json.load (train_file.read ())
Vasin Yuriy

13

먼저 파이썬 사전에서 json 데이터를 가져올 수 있습니다.

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)

또한 데이터를 문자열로 다시 덤프하지 않도록 할 수 있습니다. 팬더가 사전에서 DataFrame을 직접 만들 수 있다고 가정합니다 (오래 동안 사용하지 않았습니다 : p)


나는 여전히 json 데이터와 생성 된 사전을 사용하여 동일한 결과를 얻습니다. 데이터 프레임의 각 요소에는 자체 dict이있는 것처럼 보입니다. 나는 '데이터'를 반복하면서 위도, 경도 및 고도에 대한 별도의 목록을 작성하는 덜 매력적인 방식으로 접근 방식을 사용해 보았습니다.
pbreach 5

@ user2593236 : 안녕하세요, SO 코드를 복사 / 붙여 넣는 동안 오류가 발생했습니다 : 델이 누락되었습니다 (응답 편집 됨)
Raphaël Braud

흠 .. 여전히 '결과'와 '상태'가 헤더와 동일한 반면 나머지 json 데이터는 각 셀에서 dicts로 나타납니다. 이 문제에 대한 해결책은 데이터 형식을 '결과'와 '상태'로 세분화하지 않도록 데이터 형식을 변경하는 것이며 데이터 프레임은 'lat', 'lng', 'elevation', ' '를 별도의 헤더로 사용하십시오. 또는 질문에서 언급 한 것처럼 다중 레벨 헤더 색인이있는 데이터 프레임에 json 데이터를로드하는 방법을 찾아야합니다.
pbreach

어떤 최종 테이블을 기대하십니까? 편집 후 얻은 것?
Raphaël Braud

최종 편집 후 얻은 작업이 기본적으로 수행 한 작업은 기본적으로 데이터를 내보내고 사용할 수있는 테이블 형식으로 가져 오는 것입니다.
pbreach

9

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

4

문제는 데이터 프레임에 작은 dict가 포함 된 dict가 포함 된 열이 여러 개 있다는 것입니다. 유용한 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')

4

허용 된 답변의 최적화 :

수락 된 답변에는 기능상의 문제가 있으므로 urllib2에 의존하지 않는 코드를 공유하고 싶습니다.

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)

산출:

        _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는 덴마크 전기 가격입니다


3

다음은 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)

1

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

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

DataFrame수락 된 답변으로 얻은 평평한 것을 만들면 다음과 같이 열을 MultiIndex( "팬시 멀티 라인 헤더")로 만들 수 있습니다 .

df.columns = pd.MultiIndex.from_tuples([tuple(c.split('.')) for c in df.columns])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.