Python 将数据帧转换为嵌套JSON

Python 将数据帧转换为嵌套JSON,python,json,pandas,dataframe,Python,Json,Pandas,Dataframe,我不熟悉蟒蛇和熊猫。我正在尝试将Pandas数据帧转换为嵌套的JSON。函数.to_json()没有为我的目标提供足够的灵活性 以下是数据帧的一些数据点(csv格式,逗号分隔): 有很多重复信息,我希望有一个JSON,如下所示: [ { "ID": 1, "Location": "BREST", "Latitude": 48.383, "Longitude": -4.495, "Country": "FRA", "Tide-Data": {

我不熟悉蟒蛇和熊猫。我正在尝试将Pandas数据帧转换为嵌套的JSON。函数.to_json()没有为我的目标提供足够的灵活性

以下是数据帧的一些数据点(csv格式,逗号分隔):

有很多重复信息,我希望有一个JSON,如下所示:

[
{
    "ID": 1,
    "Location": "BREST",
    "Latitude": 48.383,
    "Longitude": -4.495,
    "Country": "FRA",
    "Tide-Data": {
        "1807-02-01": 6931,
        "1807-03-01": 6896,
        "1807-04-01": 6953,
        "1807-05-01": 7043
    }
},
{
    "ID": 5,
    "Location": "HOLYHEAD",
    "Latitude": 53.31399999999999,
    "Longitude": -4.62,
    "Country": "GBR",
    "Tide-Data": {
        "1807-02-01": 6931,
        "1807-03-01": 6896,
        "1807-04-01": 6953,
        "1807-05-01": 7043
    }
}
]
我怎样才能做到这一点

编辑:

用于复制数据帧的代码:

# input json
json_str = '[{"ID":1,"Location":"BREST","Country":"FRA","Latitude":48.383,"Longitude":-4.495,"timestamp":"1807-01-01","tide":6905},{"ID":1,"Location":"BREST","Country":"FRA","Latitude":48.383,"Longitude":-4.495,"timestamp":"1807-02-01","tide":6931},{"ID":1,"Location":"BREST","Country":"DEU","Latitude":48.383,"Longitude":-4.495,"timestamp":"1807-03-01","tide":6896},{"ID":7,"Location":"CUXHAVEN 2","Country":"DEU","Latitude":53.867,"Longitude":-8.717,"timestamp":"1843-01-01","tide":7093},{"ID":7,"Location":"CUXHAVEN 2","Country":"DEU","Latitude":53.867,"Longitude":-8.717,"timestamp":"1843-02-01","tide":6688},{"ID":7,"Location":"CUXHAVEN 2","Country":"DEU","Latitude":53.867,"Longitude":-8.717,"timestamp":"1843-03-01","tide":6493}]'

# load json object
data_list = json.loads(json_str)

# create dataframe
df = json_normalize(data_list, None, None)

更新:

j = (df.groupby(['ID','Location','Country','Latitude','Longitude'], as_index=False)
             .apply(lambda x: x[['timestamp','tide']].to_dict('r'))
             .reset_index()
             .rename(columns={0:'Tide-Data'})
             .to_json(orient='records'))
结果(格式化):

旧答案:

j = (df.groupby(['ID','Location','Country','Latitude','Longitude'], as_index=False)
             .apply(lambda x: x[['timestamp','tide']].to_dict('r'))
             .reset_index()
             .rename(columns={0:'Tide-Data'})
             .to_json(orient='records'))
您可以使用
groupby()
apply()
to_json()
方法来执行此操作:

j = (df.groupby(['ID','Location','Country','Latitude','Longitude'], as_index=False)
       .apply(lambda x: dict(zip(x.timestamp,x.tide)))
       .reset_index()
       .rename(columns={0:'Tide-Data'})
       .to_json(orient='records'))
输出:

In [112]: print(json.dumps(json.loads(j), indent=2, sort_keys=True))
[
  {
    "Country": "FRA",
    "ID": 1,
    "Latitude": 48.383,
    "Location": "BREST",
    "Longitude": -4.495,
    "Tide-Data": {
      "1807-01-01": 6905.0,
      "1807-02-01": 6931.0,
      "1807-03-01": 6896.0,
      "1807-04-01": 6953.0,
      "1807-05-01": 7043.0
    }
  },
  {
    "Country": "DEU",
    "ID": 7,
    "Latitude": 53.867,
    "Location": "CUXHAVEN 2",
    "Longitude": 8.717,
    "Tide-Data": {
      "1843-01-01": 7093.0,
      "1843-02-01": 6688.0,
      "1843-03-01": 6493.0,
      "1843-04-01": 6723.0,
      "1843-05-01": 6533.0
    }
  },
  {
    "Country": "DEU",
    "ID": 8,
    "Latitude": 53.899,
    "Location": "WISMAR 2",
    "Longitude": 11.458,
    "Tide-Data": {
      "1848-07-01": 6957.0,
      "1848-08-01": 6944.0,
      "1848-09-01": 7084.0,
      "1848-10-01": 6898.0,
      "1848-11-01": 6859.0
    }
  },
  {
    "Country": "NLD",
    "ID": 9,
    "Latitude": 51.918,
    "Location": "MAASSLUIS",
    "Longitude": 4.25,
    "Tide-Data": {
      "1848-02-01": 6880.0,
      "1848-03-01": 6700.0,
      "1848-04-01": 6775.0,
      "1848-05-01": 6580.0,
      "1848-06-01": 6685.0
    }
  },
  {
    "Country": "USA",
    "ID": 10,
    "Latitude": 37.807,
    "Location": "SAN FRANCISCO",
    "Longitude": -122.465,
    "Tide-Data": {
      "1854-07-01": 6909.0,
      "1854-08-01": 6940.0,
      "1854-09-01": 6961.0,
      "1854-10-01": 6952.0,
      "1854-11-01": 6952.0
    }
  }
]
PS如果您不关心标识,可以直接写入JSON文件:

(df.groupby(['ID','Location','Country','Latitude','Longitude'], as_index=False)
   .apply(lambda x: dict(zip(x.timestamp,x.tide)))
   .reset_index()
   .rename(columns={0:'Tide-Data'})
   .to_json('/path/to/file_name.json', orient='records'))

有很多选择。看看这些选项是否能满足您的需求。尤其是查看
orient
选项。我不知道如何实现。它一次又一次地重复所有相同的信息,但我希望将timestamp和tide列嵌套。如果要嵌套
timestamp
tide
,最好在调用
到_json
之前进行嵌套。抱歉,一开始我误解了这个问题。但我的问题是:如何将它们组合在一起?@Felix,很高兴我能提供帮助:)我刚刚意识到我需要这种格式的数据:“潮汐数据”:{“时间戳”:“1848-07-01”,“潮汐”:“6957.0”}。我必须在你的函数中更改什么?@Felix,你能在你的问题中更新你想要的JSON吗,这样我就可以看到多个(分组)条目的样子了?我认为你的更新是正确的JSON格式。我明天一开始画折线图就告诉你。非常感谢您的更新@MaxU作为新版本的pandas(例如1.2.1),它不再适用于我。我得到这个错误:ValueError:1列传递,传递的数据有n列(在我的例子中,n是5)。是什么改变了熊猫,使之成为现实?
(df.groupby(['ID','Location','Country','Latitude','Longitude'], as_index=False)
   .apply(lambda x: dict(zip(x.timestamp,x.tide)))
   .reset_index()
   .rename(columns={0:'Tide-Data'})
   .to_json('/path/to/file_name.json', orient='records'))