2014-07-20 4 views
5

Openstreetmaps API 출력 JSON 문자열을 읽으려고합니다. 유효합니다.팬더가있는 JSON을 읽을 때 '예상 문자열 또는 유니 코드'

--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-66-304b7fbfb645> in <module>() 
----> 1 osmdataframe = pd.read_json(osmdata) 

/Users/paul/anaconda/lib/python2.7/site-packages/pandas/io/json.pyc in read_json(path_or_buf, orient, typ, dtype, convert_axes, convert_dates, keep_default_dates, numpy, precise_float, date_unit) 
    196   obj = FrameParser(json, orient, dtype, convert_axes, convert_dates, 
    197       keep_default_dates, numpy, precise_float, 
--> 198       date_unit).parse() 
    199 
    200  if typ == 'series' or obj is None: 

/Users/paul/anaconda/lib/python2.7/site-packages/pandas/io/json.pyc in parse(self) 
    264 
    265   else: 
--> 266    self._parse_no_numpy() 
    267 
    268   if self.obj is None: 

/Users/paul/anaconda/lib/python2.7/site-packages/pandas/io/json.pyc in _parse_no_numpy(self) 
    481   if orient == "columns": 
    482    self.obj = DataFrame(
--> 483     loads(json, precise_float=self.precise_float), dtype=None) 
    484   elif orient == "split": 
    485    decoded = dict((str(k), v) 

TypeError: Expected String or Unicode 

어떻게 오류를 피하기 위해 요청 또는 팬더 read_json을 수정하기 : 오류

import pandas as pd 
import requests 

# Links unten 
minLat = 50.9549 
minLon = 13.55232 

# Rechts oben 
maxLat = 51.1390 
maxLon = 13.89873 

osmrequest = {'data': '[out:json][timeout:25];(node["highway"="bus_stop"](%s,%s,%s,%s););out body;>;out skel qt;' % (minLat, minLon, maxLat, maxLon)} 
osmurl = 'http://overpass-api.de/api/interpreter' 
osm = requests.get(osmurl, params=osmrequest) 

osmdata = osm.json() 

osmdataframe = pd.read_json(osmdata) 

을 다음과 같은 예외 :

나는 다음과 같은 코드를 사용하고? 그건 그렇고, 뭐가 문제 야? json으로 문자열을 파이썬 객체로 변환 할 것 인 경우에, 그것을

{ 
    "version": 0.6, 
    "generator": "Overpass API", 
    "osm3s": { 
    "timestamp_osm_base": "2014-07-20T07:52:02Z", 
    "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." 
    }, 
    "elements": [ 

{ 
    "type": "node", 
    "id": 536694, 
    "lat": 50.9849256, 
    "lon": 13.6821776, 
    "tags": { 
    "highway": "bus_stop", 
    "name": "Niederhäslich Bergmannsweg" 
    } 
}, 
...]} 

:이 같은 것을 볼 수 있습니다

content = osm.read() 
with open('/tmp/out', 'w') as f: 
    f.write(content) 

파일로 json으로 문자열을 인쇄 할 경우

답변

11

, 그 elements 키가 dicts의 목록 인 dict 일 것입니다. 대다수의 데이터는이 목록에 있습니다.

이 JSON 문자열은 팬더 개체로 직접 변환 할 수 없습니다. 인덱스 란 무엇이며 열은 무엇입니까? 거의 모든 정보가 elements list-of-dicts에 있기 때문에 확실히 [u'elements', u'version', u'osm3s', u'generator']을 열에 넣고 싶지는 않습니다.

그러나 DataFrame을 elements 목록에만있는 데이터로 구성하려면 팬더가 그 가정을 할 수 없으므로이를 지정해야합니다.

더욱 복잡한 점은 elements에있는 각각의 사전이 중첩 된 dict이라는 점입니다.

{ 
    "type": "node", 
    "id": 536694, 
    "lat": 50.9849256, 
    "lon": 13.6821776, 
    "tags": { 
    "highway": "bus_stop", 
    "name": "Niederhäslich Bergmannsweg" 
    } 
} 

해야하는 ['lat', 'lon', 'type', 'id', 'tags']가 열 수 : elements의 첫 번째 DICT을 고려? tags 열이 dicts의 열이된다는 것을 제외하면 그럴듯 해 보입니다. 그것은 대개별로 유용하지 않습니다. tags dict 내의 키가 열로 구성되어 있다면 더 좋을 것입니다. 우리는 그것을 할 수는 있지만 팬더는 우리가 원하는 것을 알 수있는 방법이 없기 때문에 다시 코딩해야합니다.


import pandas as pd 
import requests 
# Links unten 
minLat = 50.9549 
minLon = 13.55232 

# Rechts oben 
maxLat = 51.1390 
maxLon = 13.89873 

osmrequest = {'data': '[out:json][timeout:25];(node["highway"="bus_stop"](%s,%s,%s,%s););out body;>;out skel qt;' % (minLat, minLon, maxLat, maxLon)} 
osmurl = 'http://overpass-api.de/api/interpreter' 
osm = requests.get(osmurl, params=osmrequest) 

osmdata = osm.json() 
osmdata = osmdata['elements'] 
for dct in osmdata: 
    for key, val in dct['tags'].iteritems(): 
     dct[key] = val 
    del dct['tags'] 

osmdataframe = pd.DataFrame(osmdata) 
print(osmdataframe[['lat', 'lon', 'name']].head()) 

수익률

  lat  lon      name 
0 50.984926 13.682178 Niederhäslich Bergmannsweg 
1 51.123623 13.782789    Sagarder Weg 
2 51.065752 13.895734  Weißig, Einkaufszentrum 
3 51.007140 13.698498   Stuttgarter Straße 
4 51.010199 13.701411   Heilbronner Straße 
+1

멋진 설명! 나는 이것을 완벽하게 이해하지만 내 자신을 위해 수수께끼를 풀 수는 없었다. 감사! 'AttributeError : 'Response'객체에 'read'' 속성이 없습니다. – Balzer82

+0

'osmdata = json.loads (osm.read())'는 올바르지 않을 수 있습니다. = json.loads (osm.content)' – Balzer82

+0

@ Balzer82 : 요청이 너무 오래되었습니다. 그 이후 API가 변경되었습니다. 나는'requests'에 의해 업데이트했고 위의 코드를 편집 할 것입니다. – unutbu