JSON đến gấu trúc DataFrame


143

Những gì tôi đang cố gắng làm là trích xuất dữ liệu độ cao từ API google maps dọc theo một đường dẫn được chỉ định bởi các tọa độ kinh độ và vĩ độ như sau:

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

Điều này cho tôi một dữ liệu trông như thế này:

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

khi đưa vào làm DataFrame ở đây là những gì tôi nhận được:

nhập mô tả hình ảnh ở đây

pd.read_json(elevations)

và đây là những gì tôi muốn:

nhập mô tả hình ảnh ở đây

Tôi không chắc liệu điều này có khả thi hay không, nhưng chủ yếu những gì tôi đang tìm kiếm là một cách để có thể đặt dữ liệu độ cao, vĩ độ và kinh độ trong một khung dữ liệu gấu trúc (không phải có các tiêu đề mutiline ưa thích).

Nếu bất kỳ ai có thể giúp đỡ hoặc đưa ra một số lời khuyên về việc làm việc với dữ liệu này sẽ rất tuyệt! Nếu bạn không thể nói rằng tôi đã không làm việc nhiều với dữ liệu json trước khi ...

BIÊN TẬP:

Phương pháp này không hấp dẫn lắm nhưng dường như có hiệu quả:

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

kết thúc khung dữ liệu có các cột vĩ độ, kinh độ, độ cao

nhập mô tả hình ảnh ở đây


Xin chào bạn, bạn có biết làm thế nào để có được một mảnh json? một số phụ?
M.

Câu trả lời:


184

Tôi tìm thấy một giải pháp nhanh chóng và dễ dàng cho những gì tôi muốn sử dụng json_normalize()bao gồm trong 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'])

Điều này mang lại một khung dữ liệu được làm phẳng đẹp với dữ liệu json mà tôi nhận được từ API Google Maps.


12
Điều này dường như không còn hoạt động - Tôi đã phải sử dụng pd.DataFrame.from_records()như được mô tả ở đây stackoverflow.com/a/33020669/1137804
avv

4
from_records cũng không làm việc vào những thời điểm nếu json là đủ phức tạp, bạn phải áp dụng json.io.json.json_normalize để có được một Kiểm tra flatMap ra stackoverflow.com/questions/39899005/...
devssh

27

Kiểm tra bắn tỉa này.

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

Hy vọng nó giúp :)


1
Lỗi. Bạn nên chuyển nội dung tệp (tức là một chuỗi) cho json.loads (), chứ không phải chính đối tượng tệp - json.load (train_file.read ())
Vasin Yuriy

13

Trước tiên, bạn có thể nhập dữ liệu json của mình trong từ điển Python:

data = json.loads(elevations)

Sau đó sửa đổi dữ liệu một cách nhanh chóng:

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

Xây dựng lại chuỗi json:

elevations = json.dumps(data)

Cuối cùng:

pd.read_json(elevations)

Ngoài ra, bạn cũng có thể tránh để chuyển dữ liệu trở lại chuỗi, tôi cho rằng Panda có thể trực tiếp tạo DataFrame từ một từ điển (tôi đã không sử dụng nó từ lâu: p)


Tôi vẫn kết thúc với cùng một kết quả bằng cách sử dụng dữ liệu json và từ điển đã được tạo. Có vẻ như mỗi phần tử trong khung dữ liệu đều có chính tả. Tôi đã thử sử dụng cách tiếp cận của bạn theo cách kém hấp dẫn hơn để xây dựng một danh sách riêng cho lat, lng và độ cao trong khi lặp qua 'dữ liệu'.
vi phạm

@ user2593236: Xin chào, tôi đã gặp lỗi khi sao chép / dán mã của mình trong SO: a del bị thiếu (câu trả lời được chỉnh sửa)
Raphaël Braud

Hmm .. Vẫn giống nhau ở chỗ nó có 'kết quả' và 'trạng thái' làm tiêu đề trong khi phần còn lại của dữ liệu json xuất hiện dưới dạng ký tự trong mỗi ô. Tôi nghĩ rằng giải pháp cho vấn đề này là thay đổi định dạng của dữ liệu để nó không được chia thành 'kết quả' và 'trạng thái' thì khung dữ liệu sẽ sử dụng 'lat', 'lng', 'elevation', ' độ phân giải 'như các tiêu đề riêng biệt. Hoặc là vậy, hoặc tôi sẽ cần tìm cách tải dữ liệu json vào một khung dữ liệu sẽ có chỉ mục tiêu đề đa cấp như tôi đã đề cập trong câu hỏi.
vi phạm

Bàn cuối cùng nào bạn mong đợi? Một trong những bạn nhận được sau khi chỉnh sửa của bạn?
Raphaël Braud

Công cụ tôi nhận được sau khi chỉnh sửa cuối cùng thực hiện công việc, về cơ bản, tất cả những gì tôi cần là lấy dữ liệu ở định dạng bảng mà tôi có thể xuất và làm việc với
vi phạm

9

Chỉ là một phiên bản mới của câu trả lời được chấp nhận, vì python3.xkhông hỗ trợ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

Vấn đề là bạn có một số cột trong khung dữ liệu có chứa các ký tự có các ký tự nhỏ hơn bên trong chúng. Json hữu ích thường được lồng rất nhiều. Tôi đã viết các hàm nhỏ kéo thông tin tôi muốn vào một cột mới. Bằng cách đó tôi có nó ở định dạng mà tôi muốn sử dụng.

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

Tối ưu hóa câu trả lời được chấp nhận:

Câu trả lời được chấp nhận có một số vấn đề về chức năng, vì vậy tôi muốn chia sẻ mã của mình không dựa vào 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)

Đầu ra:

        _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 dành cho giá điện của Đan Mạch


3

Đây là lớp tiện ích nhỏ chuyển đổi JSON thành DataFrame và trở lại: Hy vọng bạn thấy điều này hữu ích.

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

Giải pháp của billmanH đã giúp tôi nhưng không hoạt động cho đến khi tôi chuyển từ:

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

đến:

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

Đây là phần còn lại của nó, chuyển đổi sang một từ điển là hữu ích để làm việc với dữ liệu 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

Khi bạn đã làm phẳng DataFramebằng câu trả lời được chấp nhận, bạn có thể đặt các cột thành MultiIndex("tiêu đề đa dòng ưa thích") như thế này:

df.columns = pd.MultiIndex.from_tuples([tuple(c.split('.')) for c in df.columns])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.