嗨,我正在尝试平平和解析许多键中的7个:30个嵌套的大型.json.gz文件中的值对(解压缩前每个文件4GB)。我正在尝试做标准的熊猫和json组合,但是一排一行地读30个大的json文件似乎并不是最好的主意,所以经过一些搜索,我发现dask很快就做到了。我正在使用这个函数,我能够将每个json对象的7个字段迅速地压平。
目标是获取所有具有key:screen
和value:CAMERA
的json对象。问题是这些文件中的所有json对象都有key=screen
。若要对没有key=screen
的行重写该键错误,请执行我知道的不建议的操作;尝试并捕获块。虽然这样做有效,但它只是创建了一堆None
行,并且无法迅速删除它们。为了更清楚地说明,None
行是在没有什么可扁平的地方创建的,因为这个特定的json对象没有screen
键。我希望找到一种方法来过滤和平平基于键而不仅仅是值的json文件。或者*b)*为dask袋子找到一个快速的dropna()
等价,这样我就可以在一个命令中消除所有这些None
行。
最终的目标是对2018年3月的所有文件都这样做,并将它们编译成一个数据,以供进一步分析。
我尝试过使用其他命令和方法,这些命令和方法不涉及使用ijson
模块和整个前缀、值(请参阅下面代码截图中的注释部分)。考虑到我的文件大小,没有哪个替代方法像dask.bag
方法那样快速高效。一个理想的解决方案是找到一种解决None
行问题的方法。
import dask.bag as db
import json
import gzip
import pandas as pd
import ijson as ij
path="etl/mar2018/mongo-feedback-2018-03-05.json.gz"
# pd.read_json(path)
# b=ij.parse(path)
# print(b)
# def parse_json(json_filename):
# with gzip.open(path,'rt', encoding='utf-8') as input_file:
# # with open(json_filename, 'rb')
# # load json iteratively
# parser = ijson.parse(input_file)
# # return ij.items(parser)
# for prefix, event, value in parser:
# if prefix=='screen':
# print(value)
# # print(prefix)
# # print('prefix={}, event={}, value={}'.format(prefix, event, value))
# # if __name__ == '__main__':
# parse_json(path)
# b.head()
b=db.read_text(path).map(json.loads)
# b.to_dataframe()
# b=b.filter(lambda record: record['screen'])
# # for i in b:
# # print(i)
# #
def flatten(record):
try:
return{
'userId': record['userId'],
'expression':record['expression'],
'platform':record['platform'],
'country':record['country'],
"date":record['date']['$date'],
"cameraImageType":record['metadataMap']["cameraImageType"],
"screen":record['screen']
}
except KeyError:
pass
df=b.map(flatten)
df.take(5)
# df.remove(None)
def filter1(record):
if record is None:
return record
# df.to_textfiles()
# .to_dataframe()
# p=df.map(filter1)
# df1=df-p
# # df.compute()
# # df.notnull().take(10)
# # df.dropna(how='all')
# # df.head(50)
# # p=filter(None,df)
# # list(b.filter('screen'))
# # b.count().compute()
# p=df.to_csv()
# d=df.dropna()
# d.head()
# # b.filter(lambda record: record['screen']=='CAMERA').take(10)
(无,无,{'userId':'foo',‘表达式’:'bar','platform':'IOS','country':'GT',‘日期’:'2018-03-04T22:58:18.000Z','cameraImageType':‘键入’,‘屏幕’:‘照相机’},无)在这里输入图像描述)
发布于 2019-05-27 23:41:30
如果我理解正确的话,您的书包中包含了一些元素,其中一些元素带有实际数据作为字典,还有一些元素的值仅为None
,在这些元素中找不到键--您希望只保存真实数据。
我将使用filter
方法:
b2 = b.map(flatten).filter(bool)
(或者,更明确地说,用bool
替换为lambda x: x is not None
;这是一个函数,指定是否保留给定的元素)
然后,您可以将其写入文件,或将其转换为数据,并对其执行进一步的操作。
https://stackoverflow.com/questions/56330229
复制相似问题