1

I have this (subset) Pandas dataframe:

enter image description here

I read it from an XLSX file. I would like to convert it to geopandas GeoDataFrame. In order to do so, I need a valid geometry column. The GeoJSON column in my dataframe is of type object (string). This is how the first row looks like:

print (df['geojson'][0])

'{ "type": "MultiPolygon", "coordinates":[[[[64.3325537508718, 39.7951221200142], [64.3314543541686, 39.7929546433382], [64.3347958014419, 39.7926500279878], [64.3356495283569, 39.7941461414354], [64.3325537508718, 39.7951221200142]]]]}'

I can convert this to valid GeoPandas geometry (i.e., Python dictionary, JSON format) with:

print (json.loads(df['geojson'][0]))

{'type': 'MultiPolygon',
 'coordinates': [[[[64.3325537508718, 39.7951221200142],
    [64.3314543541686, 39.7929546433382],
    [64.3347958014419, 39.7926500279878],
    [64.3356495283569, 39.7941461414354],
    [64.3325537508718, 39.7951221200142]]]]}

Now, I would like to do that for each row but when I try it as a function with apply or as a for loop I get an error. I don't understand why for a single row it works but for all rows, it fails.

def json_load(k):
    return json.loads(k)

df['geojson'].apply(json_load)

---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
<ipython-input-58-cd5fe341c8cf> in <module>
      2     return json.loads(k)
      3 
----> 4 df['geojson'].apply(json_load)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\series.py in apply(self, func, convert_dtype, args, **kwds)
   4040             else:
   4041                 values = self.astype(object).values
-> 4042                 mapped = lib.map_infer(values, f, convert=convert_dtype)
   4043 
   4044         if len(mapped) and isinstance(mapped[0], Series):

pandas\_libs\lib.pyx in pandas._libs.lib.map_infer()

<ipython-input-58-cd5fe341c8cf> in json_load(k)
      1 def json_load(k):
----> 2     return json.loads(k)
      3 
      4 df['geojson'].apply(json_load)

~\AppData\Local\Continuum\anaconda3\lib\json\__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    346             parse_int is None and parse_float is None and
    347             parse_constant is None and object_pairs_hook is None and not kw):
--> 348         return _default_decoder.decode(s)
    349     if cls is None:
    350         cls = JSONDecoder

~\AppData\Local\Continuum\anaconda3\lib\json\decoder.py in decode(self, s, _w)
    335 
    336         """
--> 337         obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    338         end = _w(s, end).end()
    339         if end != len(s):

~\AppData\Local\Continuum\anaconda3\lib\json\decoder.py in raw_decode(self, s, idx)
    351         """
    352         try:
--> 353             obj, end = self.scan_once(s, idx)
    354         except StopIteration as err:
    355             raise JSONDecodeError("Expecting value", s, err.value) from None

JSONDecodeError: Expecting ',' delimiter: line 1 column 251 (char 250)

and for loop, the same:

for i in df['geojson']:
    a = json.loads(i)

---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
<ipython-input-51-bfcce15a3cba> in <module>
      1 for i in df['geojson']:
----> 2     a = json.loads(i)

~\AppData\Local\Continuum\anaconda3\lib\json\__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    346             parse_int is None and parse_float is None and
    347             parse_constant is None and object_pairs_hook is None and not kw):
--> 348         return _default_decoder.decode(s)
    349     if cls is None:
    350         cls = JSONDecoder

~\AppData\Local\Continuum\anaconda3\lib\json\decoder.py in decode(self, s, _w)
    335 
    336         """
--> 337         obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    338         end = _w(s, end).end()
    339         if end != len(s):

~\AppData\Local\Continuum\anaconda3\lib\json\decoder.py in raw_decode(self, s, idx)
    351         """
    352         try:
--> 353             obj, end = self.scan_once(s, idx)
    354         except StopIteration as err:
    355             raise JSONDecodeError("Expecting value", s, err.value) from None

JSONDecodeError: Expecting ',' delimiter: line 1 column 251 (char 250)

I understand that there is allegedly a problem with character 250 in the string, but it works for a single row.

  • 2
    From your question, the json decode works on the first row, but not when you put it in the loop. But which iteration of the loop (i.e. row of the dataframe) is it failing on? Perhaps one row contains a problematic geojson? Perhaps you can print i on each loop to see the json to be decoded, or at least use enumerate in the loop to see what iteration/row the error is occurring on? – sbphd Jan 9 at 8:28
  • 1
    ohh.. you are correct, what a novice mistake.. I was sure that this error happened on the first row which is valid.. but I had a corrupted format. I removed it and it works.. – user88484 Jan 9 at 8:55