Генератор строк Json (Jsonl) в формат csv

У меня есть большой файл Jsonl (6 ГБ+), который мне нужно преобразовать в формат .csv. После запуска:

import json

with open(root_dir + 'filename.json') as json_file:
  for line in json_file:
    data = json.loads(line)
    print(data)

Возвращается много записей следующего формата:

{'url': 'https://twitter.com/CHItraders/status/945958273861275648', 'date': '2017-12-27T10:03:22+00:00', 'content': 'Why #crypto currencies like $BTC#Bitcoin are set for global domination - MUST READ! - https :// t.co/C1kEhoLaHr https :// t.co/sZT43PBDrM', 'renderedContent': 'Why #crypto currencies like $BTC#Bitcoin are set for global domination - MUST READ! - BizNews.com biznews.com/wealth-buildin…', 'id': 945958273861275648, 'username': 'CHItraders', 'user': {'username': 'CHItraders', 'displayname': 'CHItraders', 'id': 185663478, 'description': 'Options trader. Market-news. Nothing posted constitutes as advice. Do your own diligence.', 'rawDescription': 'Options trader. Market-news. Nothing posted constitutes as advice. Do your own diligence.', 'descriptionUrls': [], 'verified': False, 'created': '2010-09-01T14:52:28+00:00', 'followersCount': 1196, 'friendsCount': 490, 'statusesCount': 38888, 'favouritesCount': 10316, 'listedCount': 58, 'mediaCount': 539, 'location': 'Chicago, IL', 'protected': False, 'linkUrl': None, 'linkTcourl': None, 'profileImageUrl': 'https://pbs.twimg.com/profile_images/623935252357058560/AaeCRlHB_normal.jpg', 'profileBannerUrl': 'https://pbs.twimg.com/profile_banners/185663478/1437592670'}, 'outlinks': ['http://BizNews.com', 'https://www.biznews.com/wealth-building/2017/12/27/bitcoin-rebecca-mqamelo/#.WkNv2bQ3Awk.twitter'], 'outlinksss': 'http://BizNews.com https://www.biznews.com/wealth-building/2017/12/27/bitcoin-rebecca-mqamelo/#.WkNv2bQ3Awk.twitter', 'tcooutlinks': ['https :// t.co/C1kEhoLaHr', 'https :// t.co/sZT43PBDrM'], 'tcooutlinksss': 'https :// t.co/C1kEhoLaHr https :// t.co/sZT43PBDrM', 'replyCount': 0, 'retweetCount': 0, 'likeCount': 0, 'quoteCount': 0, 'conversationId': 945958273861275648, 'lang': 'en', 'source': '<a href = "http://twitter.com" rel = "nofollow">Twitter Web Client</a>', 'media': None, 'retweetedTweet': None, 'quotedTweet': None, 'mentionedUsers': None}

Из-за размера файла я не могу использовать преобразование:

with open(root_dir + 'filename.json', 'r', encoding ='utf-8-sig') as f:
    data = f.readlines()

data = map(lambda x: x.rstrip(), data)
data_json_str = "[" + ','.join(data) + "]"
newdf = pd.read_json(StringIO(data_json_str))
newdf.to_csv(root_dir + 'output.csv')

из-за MemoryError. Я пытаюсь использовать приведенный ниже генератор и записывать каждую строку в csv, что должно устранить проблему MemoryError:

def yield_line_delimited_json(path):
    """
    Read a line-delimited json file yielding each row as a record
    :param str path:
    :rtype: list[object]
    """
    with open(path, 'r') as json_file:
        for line in json_file:
            yield json.loads(line)

new = yield_line_delimited_json(root_dir + 'filename.json')

with open(root_dir + 'output.csv', 'w') as f:
    for x in new:
        f.write(str(x))

Однако данные не записываются в формате .csv. Любые советы о том, почему данные не записываются в файл csv, очень ценятся!

Ваш пример вообще недействителен JSON. Это похоже на частичный словарь Python с некоторыми повреждениями.

tripleee 17.12.2020 11:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
3 832
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Генератор кажется совершенно лишним.

with open(root_dir + 'filename.json') as old, open(root_dir + 'output.csv', 'w') as csvfile:
    new = csv.writer(csvfile)
    for x in old:
        row = json.loads(x)
        new.writerow(row)

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

Если можно ожидать, что ваш JSON будет надежно содержать один словарь с фиксированным набором пар ключевое слово-значение, возможно, попробуйте

from csv import DictWriter
import json

with open(jsonfile, 'r') as inp, open(csvfile, 'w') as outp:
    writer = DictWriter(outp, fieldnames=[
            'url', 'date', 'content', 'renderedContent', 'id', 'username',
            # 'user',  # see below
            'outlinks', 'outlinksss', 'tcooutlinks', 'tcooutlinksss',
            'replyCount', 'retweetCount', 'likeCount', 'quoteCount',
            'conversationId', 'lang', 'source', 'media', 'retweetedTweet',
            'quotedTweet', 'mentionedUsers'])
    for line in inp:
        row = json.loads(line)
        writer.writerow(row)

Я пропустил поле user, потому что в вашем примере этот ключ содержит вложенную структуру, которую нельзя легко преобразовать в CSV без дальнейшего искажения. Возможно, вы хотели бы извлечь просто user.id в новое поле user_id; или, возможно, вы хотели бы преобразовать всю структуру user в сглаженный список дополнительных столбцов в основной записи, таких как user_username, user_displayname, user_id и т. д.?

Более подробно, CSV — это, по сути, двумерная матрица, где каждая строка представляет собой одномерный набор столбцов, соответствующих одной записи в данных, где каждый столбец может содержать одну строку или одно число. В каждой строке должно быть одинаковое количество столбцов, хотя некоторые из них можно оставить пустыми.

JSON, который можно тривиально преобразовать в CSV, будет выглядеть так:

["Adolf", "1945", 10000000]
["Joseph", "1956", 25000000]
["Donald", null, 1000000]

JSON, который можно преобразовать в CSV с помощью некоторого преобразования (которое вам нужно будет указать отдельно, например, с указанным выше порядком ключей словаря), может выглядеть так:

{"name": "Adolf", "dod": "1945", "death toll": 10000000}
{"dod": "1956", "name": "Joseph", "death toll": 25000000}
{"death toll": 1000000, "name": "Donald"}

(Просто чтобы сделать его более интересным, одно поле отсутствует, а порядок словаря варьируется от одной записи к другой. Это не типично, но определенно находится в области допустимых крайних случаев, которые Python не может самостоятельно догадаться, как ручка.)

Большинство реальных JSON значительно сложнее, чем любой из этих простых примеров, до такой степени, что мы можем сказать, что проблему невозможно решить в общем случае без ручной работы с вашей стороны, чтобы отделить и нормализовать данные, которые вы хотите в структуру, подходящую для представления в виде матрицы CSV.

Другие вопросы по теме