Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:将200k JSON文件读入数据帧_Python_Json_Pandas_Dataframe - Fatal编程技术网

Python:将200k JSON文件读入数据帧

Python:将200k JSON文件读入数据帧,python,json,pandas,dataframe,Python,Json,Pandas,Dataframe,我对python非常陌生(1000之间变化,但这50个属性是1000的子集 以下是一个json文件的片段: { "study_type" : "Observational", "intervention.intervention_type" : "Device", "primary_outcome.time_frame" : "24 months", "primary_completion_date.type" : "Actual", "design_info.primary_purpose"

我对python非常陌生(<2周),被要求将提供给我的200k+JSON文件(按原样)读入一个数据库(使用python)。这些JSON文件具有简单的一级属性,在50->1000之间变化,但这50个属性是1000的子集

以下是一个json文件的片段:

{
"study_type" : "Observational",
"intervention.intervention_type" : "Device",
"primary_outcome.time_frame" : "24 months",
"primary_completion_date.type" : "Actual",
"design_info.primary_purpose" : "Diagnostic",
"design_info.secondary_purpose" : "Intervention",
"start_date" : "January 2014",
"end_date" : "March 2014",
"overall_status" : "Completed",
"location_countries.country" : "United States",
"location.facility.name" : "Generic Institution",
}
我们的目标是获取这些JSON文件的主数据库,清理各个列,对这些列运行描述性统计,并创建最终的清理数据库

我来自SAS公司,所以我的想法是使用pandas并创建一个(非常)大的数据帧。在过去的一周里,我一直在梳理堆栈溢出问题,并利用了一些经验教训,但我觉得必须有一种方法使这种方法更有效

下面是我到目前为止编写的代码——它运行起来很慢(我估计即使在消除了不必要的输入属性/以“result”开头的列之后,运行起来也需要几天,甚至几周)

此外,我将字典转换为最终表的笨拙方式将列索引号保留在列名上方,而我一直不知道如何删除

import json, os
import pandas as pd    
from copy import deepcopy

path_to_json = '/home/ubuntu/json_flat/'

#Gets list of files in directory with *.json suffix
list_files = [pos_json for pos_json in os.listdir(path_to_json) if pos_json.endswith('.json')]

#Initialize series
df_list = []

#For every json file found
for js in list_files:

    with open(os.path.join(path_to_json, js)) as data_file:
        data = json.loads(data_file.read())                         #Loads Json file into dictionary
        data_file.close()                                           #Close data file / remove from memory

        data_copy = deepcopy(data)                                  #Copies dictionary file
        for k in data_copy.keys():                                  #Iterate over copied dictionary file
            if k.startswith('result'):                              #If field starts with "X" then delete from dictionary
                del data[k]
        df = pd.Series(data)                                        #Convert Dictionary to Series
        df_list.append(df)                                          #Append to empty series  
        database = pd.concat(df_list, axis=1).reset_index()         #Concatenate series into database

output_db = database.transpose()                                    #Transpose rows/columns
output_db.to_csv('/home/ubuntu/output/output_db.csv', mode = 'w', index=False)
非常感谢您的任何想法和建议。我完全愿意使用完全不同的技术或方法(在python中),如果它更有效并且仍然允许我们实现上述目标的话


谢谢!

您最关键的性能缺陷可能是:

database = pd.concat(df_list, axis=1).reset_index()
您可以在循环中执行此操作,每次向
df_list
中添加一个以上的内容,然后再次执行concat。但是直到最后,此“数据库”变量才可用,因此您可以在循环之外执行此步骤一次

对于熊猫来说,循环中的“concat”是一个巨大的反模式。在循环中建立你的列表,concat立刻

第二件事是,您还应该使用Pandas来读取JSON文件:

保持简单。编写一个函数,该函数采用路径,调用
pd.read\u json()
,删除不需要的行(
series.str.startswith()
),等等


一旦工作正常,下一步将检查您是CPU受限(CPU使用率100%)还是I/O受限(CPU使用率远低于100%).

我尝试以更简洁的方式复制您的方法,减少复制和附加。它适用于您提供的示例数据,但不知道您的数据集中是否存在进一步的复杂性。您可以尝试一下,我希望评论能有所帮助

import json
import os
import pandas
import io


path_to_json = "XXX"

list_files = [pos_json for pos_json in os.listdir(path_to_json) if pos_json.endswith('.json')]

#set up an empty dictionary
resultdict = {}

for fili in list_files:
    #the with avoids the extra step of closing the file
    with open(os.path.join(path_to_json, fili), "r") as inputjson:
        #the dictionary key is set to filename here, but you could also use e.g. a counter
        resultdict[fili] = json.load(inputjson)
        """
        you can exclude stuff here or later via dictionary comprehensions: 
        http://stackoverflow.com/questions/1747817/create-a-dictionary-with-list-comprehension-in-python
        e.g. as in your example code
        resultdict[fili] = {k:v for k,v in json.load(inputjson).items() if not k.startswith("result")}
        """

#put the whole thing into the DataFrame     
dataframe = pandas.DataFrame(resultdict)

#write out, transpose for desired format
with open("output.csv", "w") as csvout:
    dataframe.T.to_csv(csvout)

请注意,您可以使用
json.load()
()直接读取文件。无需添加
read()
并执行
json.load()
。此外,为什么不将所有json读入一个大字典,然后将整个字典转换为一个
数据框架(请参阅)您可以写入文件。谢谢Patrick!感谢提示,我会做出更改。这似乎不会对运行时间造成太大影响,但每一个效率都会有所帮助。@Patrick在我回应时刚刚看到了您的第二篇帖子。让我试一试。谢谢John,单是这一行的移动就极大地改变了运行时间。就我而言,我无法获得startswith()函数来处理此系列(我可以在这些文件上使用“read_json()”的唯一方法是:typ='series'和orient='records'w/o error)。-----------------------------------------------------------------------------------------
如果不是data.str.startswith('results'):
(返回一个ValueError)Patrick,这很好!它完美地去除了列索引值。我遇到的问题(JSONDecodeError)是我是否取消了对排除条件的注释。它看起来像是结果
resultdct[fili]
在转换为数据帧之前,有一个包含键/值对的json文件名和值的键。再次感谢您的任何想法/建议。@RDara在这样做时,您需要注释掉第一步,去掉排除项。这样做了吗?对不起,您指的是哪一步?基本上我在下面的行中添加了:
resultdct[file]={k:v代表k,v在json.load(inputjson).items()中,如果不是k.startswith(“location”)}
(更改为“location”,因为它在上面的示例json文件中)…感谢您的耐心!我要补充的是,我最初花了90多分钟的时间在10k个文件的子集上减少到了几秒钟。刚刚在200k+的JSON文件上进行了测试(提取了一部分字段),这似乎也相当快。真是太感谢您了!!您可以将文件名传递到
到_csv()
-不需要在那里打开()。