Нужна помощь в удалении None строк из объекта dask для нескольких больших файлов JSON - PullRequest
0 голосов
/ 27 мая 2019

Привет. Я пытаюсь сгладить и проанализировать только 7 из многих ключей: пары значений из 30 вложенных больших файлов .json.gz (по 4 ГБ каждый перед распаковкой).Я пытаюсь выполнить стандартную комбинацию pandas и json, но чтение строк по одной строке для 30 больших файлов json не кажется лучшей идеей, поэтому после некоторых поисков я нашел dask, который сделал это очень быстро.Я использую эту функцию, и мне удалось быстро сгладить 7 полей, которые мне нужны для каждого объекта json.

изображение кода ноутбука jupyter и вместе с результатом

Цель состоит в том, чтобы захватить все объекты json, которые имеют key:screen и value:CAMERA.Проблема не во всех объектах json в этих файлах key=screen.Чтобы переопределить эту ключевую ошибку для строк, где нет key=screen, я делаю то, что, как я знаю, не рекомендуется;попробуйте поймать блок.Хотя это работает, он просто создает кучу None строк, и их невозможно быстро удалить.Для большей ясности строки None создаются в местах, где нечего было сглаживать, потому что этот конкретный объект json не имел ключа screen.Я хочу найти либо a) способ отфильтровывать и выравнивать файлы json по ключу, а не только по значению.ИЛИ * b) * Найдите быстрый dropna() эквивалент для сумок для сумок, чтобы я мог избавиться от всех этих None строк в одной команде.

Конечная цель - сделать это для всех файлов на март 2018 исобрать их в один фрейм данных для дальнейшего анализа.

Я пытался использовать другие команды и методы, которые не включают использование dask, например, модуля 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', 'expression': 'bar', 'platform': 'IOS', 'country': 'GT', 'date': '2018-03-04T22: 58: 18.000Z', 'cameraImageType': 'typed', 'screen': 'CAMERA'}, None, None) введите описание изображения здесь

1 Ответ

1 голос
/ 28 мая 2019

Если я правильно понимаю, ваша сумка содержит некоторые элементы с реальными данными в виде словарей, а некоторые - только со значением None, где ключи не могут быть найдены - вы хотели бы сохранить только реальные данные.

Я бы использовал метод filter:

b2 = b.map(flatten).filter(bool)

(или, чтобы быть более точным, замените bool на lambda x: x is not None; это функция, которая определяет,Вы хотите сохранить данный элемент или нет)

Затем вы можете записать это в файлы или превратить в массив данных и выполнить с ним дальнейшие операции.

...