【问题标题】:Python: Json unpacking into a dataframePython:将 Json 解包到数据框中
【发布时间】:2018-07-14 09:21:48
【问题描述】:

我正在尝试将从 api 收到的 json 解析为 pandas DataFrame。那个 json 是分层的,在这个例子中,我有城市代码、线路名称和这条线路的车站列表。不幸的是,我无法“解包”它。非常感谢您的帮助和解释。

json:

{'id': '1',
 'lines': [{'hex_color': 'FFCD1C',
   'id': '8',
   'name': 'Калининская',          <------Line name
   'stations': [{'id': '8.189',
     'lat': 55.745113,
     'lng': 37.864052,
     'name': 'Новокосино',         <------Station 1   
     'order': 0},
    {'id': '8.88',
     'lat': 55.752237,
     'lng': 37.814587,
     'name': 'Новогиреево',        <------Station 2
     'order': 1},
etc.

我正在尝试从最低级别接收所有信息并添加所有更高级别的信息(从 linename 开始):

c = r.content
j = simplejson.loads(c)

tmp=[]
i=0
data1=pd.DataFrame(tmp)
data2=pd.DataFrame(tmp)

pd.concat
station['name']

for station in j['lines']:

    data2 = data2.append(pd.DataFrame(station['stations'], station['name']),ignore_index=True)
data2

再一次 - 问题是: 如何让它发挥作用? 这个解决方案是最佳解决方案,还是我应该了解一些功能?

更新: Json 解析正常:

json_normalize(j)

id  lines                                              name
1   [{'hex_color': 'FFCD1C', 'stations': [{'lat': ...   Москва

我能得到的当前DataFrame:

data2 = data2.append(pd.DataFrame(station['stations']),ignore_index=True)
    id      lat         lng         name        order
0   8.189   55.745113   37.864052   Новокосино  0
1   8.88    55.752237   37.814587   Новогиреево 1

所需的数据框可以表示为:

id  lat     lng                     name            order  Line_Name    Id_Top Name_Top
0   8.189   55.745113   37.864052   Новокосино      0      Калининская  1       Москва 
1   8.88    55.752237   37.814587   Новогиреево     1      Калининская  1       Москва

【问题讨论】:

  • 请发布包含至少两个顶级元素('id': '1''id': '2')的 JSON,并确保它可以被解析(它应该是有效的 JSON/字典)并提供您的所需的数据集
  • @MaxU 很有趣,但我正在使用的 Json 现在只有 1 个顶级元素。我会在一分钟内编辑问题。
  • 好的,你能发布你想要的数据集/DF吗?

标签: python json pandas dataframe


【解决方案1】:

假设你有以下字典:

In [70]: data
Out[70]:
{'id': '1',
 'lines': [{'hex_color': 'FFCD1C',
   'id': '8',
   'name': 'Калининская',
   'stations': [{'id': '8.189',
     'lat': 55.745113,
     'lng': 37.864052,
     'name': 'Новокосино',
     'order': 0},
    {'id': '8.88',
     'lat': 55.752237,
     'lng': 37.814587,
     'name': 'Новогиреево',
     'order': 1}]}]}

解决方案:使用pandas.io.json.json_normalize

In [71]: pd.io.json.json_normalize(data['lines'],
                                   ['stations'],
                                   ['name', 'id'],
                                   meta_prefix='parent_')
Out[71]:
      id        lat        lng         name  order  parent_name parent_id
0  8.189  55.745113  37.864052   Новокосино      0  Калининская         8
1   8.88  55.752237  37.814587  Новогиреево      1  Калининская         8

更新:反映了更新的问题

res = (pd.io.json.json_normalize(data,
                                 ['lines', 'stations'],
                                 ['id', ['lines', 'name']],
                                 meta_prefix='Line_')
         .assign(Name_Top='Москва'))

结果:

In [94]: res
Out[94]:
      id        lat        lng         name  order Line_id Line_lines.name Name_Top
0  8.189  55.745113  37.864052   Новокосино      0       1     Калининская   Москва
1   8.88  55.752237  37.814587  Новогиреево      1       1     Калининская   Москва

【讨论】:

  • 谢谢!这解决了 80% 的问题,而且比我的解决方案优雅得多。但是比名字高了2级,怎么能多加一级呢?
【解决方案2】:

除了MaxU的回答,我觉得你还是需要最高级别的id,这样应该可以的:

json_normalize(data, ['lines','stations'], ['id',['lines','name']],record_prefix='station_')

【讨论】:

  • 谢谢!就是这样!
  • 很高兴它有帮助!
  • 不错的一个! +1 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 2017-05-14
  • 1970-01-01
  • 2020-08-24
  • 2015-04-03
  • 2021-12-22
相关资源
最近更新 更多