如何使用熊猫通过多层嵌套将csv转换为json

时间:2019-03-23 21:15:44

标签: python pandas csv

我尝试遵循在SO上看到的一堆答案,但是我真的被困在这里。我正在尝试将CS​​V转换为JSON。

JSON模式具有多层嵌套,并且CSV中的某些值将被共享。

Here's a link转换为CSV中的一条记录。

将此示例视为两个不同的方附加到一个文档中。

文档上的字段(document_source_id,document_amount,record_date,source_url,document_file_url,document_type__title,apn,situs_county_id,state_code)不应重复。

每个实体的字段都是唯一的。

我曾尝试使用复杂的groupby语句嵌套它们,但一直无法将数据放入我的模式中。

这就是我尝试过的。它不包含所有字段,因为我很难理解所有含义。

j = (df.groupby(['state_code', 
                 'record_date',
                 'situs_county_id',
                 'document_type__title',
                 'document_file_url',
                 'document_amount',
                 'source_url'], as_index=False)
             .apply(lambda x: x[['source_url']].to_dict('r'))
             .reset_index()
             .rename(columns={0:'metadata', 1:'parcels'})
             .to_json(orient='records'))

这是示例CSV的输出方式

{
   "metadata":{
      "source_url":"https://a836-acris.nyc.gov/DS/DocumentSearch/DocumentDetail?doc_id=2019012901225004",
      "document_file_url":"https://a836-acris.nyc.gov/DS/DocumentSearch/DocumentImageView?doc_id=2019012901225004"
   },
   "state_code":"NY",
   "nested_data":{
      "parcels":[
         {
            "apn":"3972-61",
            "situs_county_id":"36005"
         }
      ],
      "participants":[
         {
            "entity":{
               "name":"5 AIF WILLOW, LLC",
               "situs_street":"19800 MACARTHUR BLVD",
               "situs_city":"IRVINE",
               "situs_unit":"SUITE 1150",
               "state_code":"CA",
               "situs_zip":"92612"
            },
            "participation_type":"Grantee"
         },
         {
            "entity":{
               "name":"5 ARCH INCOME FUND 2, LLC",
               "situs_street":"19800 MACARTHUR BLVD",
               "situs_city":"IRVINE",
               "situs_unit":"SUITE 1150",
               "state_code":"CA",
               "situs_zip":"92612"
            },
            "participation_type":"Grantor"
         }
      ]
   },
   "record_date":"01/31/2019",
   "situs_county_id":"36005",
   "document_source_id":"2019012901225004",
   "document_type__title":"ASSIGNMENT, MORTGAGE"
}

2 个答案:

答案 0 :(得分:0)

您可能需要使用pandas.io.json中的json_normalize函数

from pandas.io.json import json_normalize
import csv
li = []
with open('filename.csv', 'r') as f:
    reader = csv.DictReader(csvfile)
        for row in reader:
          li.append(row)
df = json_normalize(li)

在这里,我们正在从csv文件创建词典列表,并从函数json_normalize创建数据框。

答案 1 :(得分:0)

以下是导出数据的一种方法:

# all columns used in groupby()
grouped_cols = ['state_code', 'record_date', 'situs_county_id', 'document_source_id'
    , 'document_type__title', 'source_url', 'document_file_url']

# adjust some column names to map to those in the 'entity' node in the desired JSON
situs_mapping = {
    'street_number_street_name': 'situs_street'
,   'city_name': 'situs_city'
,   'unit': 'situs_unit'
,   'state_code': 'state_code'
,   'zipcode_full': 'situs_zip'
}
# define columns used for 'entity' node. python 2 need to adjust to the syntax
entity_cols = ['name', *situs_mapping.values()]
#below for python 2#
#entity_cols = ['name'] + list(situs_mapping.values())

# specify output fields
output_cols = ['metadata','state_code','nested_data','record_date'
    , 'situs_county_id', 'document_source_id', 'document_type__title']

# define a function to get nested_data
def get_nested_data(d):
    return {
        'parcels': d[['apn', 'situs_county_id']].drop_duplicates().to_dict('r')
    ,   'participants': d[['entity', 'participation_type']].to_dict('r')
    }

j = (df.rename(columns=situs_mapping)
    .assign(entity=lambda x: x[entity_cols].to_dict('r'))
    .groupby(grouped_cols)
    .apply(get_nested_data)
    .reset_index()
    .rename(columns={0:'nested_data'})
    .assign(metadata=lambda x: x[['source_url', 'document_file_url']].to_dict('r'))[output_cols]
    .to_json(orient="records")
)

print(j)

注意::如果participants包含重复项,并且必须像在parcels上一样必须运行drop_duplicates(),则可以将assign(entity)移至定义{ participants函数中的{1}}:

get_nested_data()