Как заменить определенное поле внутри строки JSON в каждой строке файла csv в Python случайным значением?

У меня есть файл CSV с именем input.csv и следующими столбцами:

номер_строки start_date_time идентификатор json_message 120 2024-02-02 00:01:00.001+00 1020240202450 {'сумма': 10000, 'валюта': 'NZD', 'seqnbr': 161 } 121 2024-02-02 00:02:00.001+00 1020240202451 {'сумма': 20000, 'валюта': 'AUD', 'seqnbr': 162 } 122 2024-02-02 00:03:00.001+00 1020240202452 {'сумма': 30000, 'валюта': 'доллары США', 'seqnbr': нет } 123 2024-02-02 00:04:00.001+00 1020240202455 {'сумма': 40000, 'валюта': 'индийская рупия', 'seqnbr': 163 }

Я использую python3 для чтения этого CSV-файла, и мне нужно заменить поле seqnbr в столбце json_message случайной целой цифрой для каждой строки. Если seqnbr содержит None, то эту строку не следует заменять случайной последовательностью, а следует оставить как есть. Разделителем моего файла CSV является символ вертикальной черты (|). Я использую приведенный ниже код Python, чтобы заменить файл случайным сгенерированным целочисленным значением, но он все равно не перезаписывает его, и вот мой код:

def update_seqnbr(cls):
    filename = 'input.csv'
    seqnbr_pattern = "'seqnbr': ([\s\d]+)"
    with open(filename, 'r') as csvfile:
        datareader = (csv.reader(csvfile, delimiter = "|"))
        next(datareader, None)  # skip the headers
        for row in datareader:
            json_message = row[3]
            match = re.findall(seqnbr_pattern, json_message)
            if len(match) != 0:
                replaced_json_message = json_message.replace(match[0], str(random.randint(500, 999)))
                row[3] = replaced_json_message
                x = open(filename, "a")
                x.writelines(row)
                x.close()

Ниже показано, как должен выглядеть мой файл:

номер_строки start_date_time идентификатор json_message 120 2024-02-02 00:01:00.001+00 1020240202450 {'сумма': 10000, 'валюта': 'NZD', 'seqnbr': 555 } 121 2024-02-02 00:02:00.001+00 1020240202451 {'сумма': 20000, 'валюта': 'AUD', 'seqnbr': 897 } 122 2024-02-02 00:03:00.001+00 1020240202452 {'сумма': 30000, 'валюта': 'доллары США', 'seqnbr': нет } 123 2024-02-02 00:04:00.001+00 1020240202455 {'сумма': 40000, 'валюта': 'индийская рупия', 'seqnbr': 768 }

Может кто-нибудь помочь мне с этим?

Однако в этом примере json_message не является допустимым JSON — это текст Python «repr». У вас действительно есть необработанные данные JSON или нет?

jqurious 03.07.2024 14:26

@jqurious, это репродукция Python. Чтобы сделать это действительным JSON, мы затем используем json_string = (col[3]).replace("'", '"') и передаем Jsonb(eval(json_string)) в нашем SQL-запросе.

Balaji Venkatachalam 03.07.2024 20:14
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
98
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

#import numpy as np

df.with_columns(
    pl.col.json_message.str.json_decode()
).with_columns(
    pl.col.json_message.struct.with_fields(
        seqnbr = 
            pl.when(
                pl.field("seqnbr").is_not_null()
            ).then(
                pl.int_range(500, 999).sample(pl.len())
                #np.random.randint(500, 999, len(df))
            )
    ).struct.json_encode()
)

┌─────────┬────────────────────────────┬───────────────┬────────────────────────────────────────────────┐
│ row_num ┆ start_date_time            ┆ id            ┆ json_message                                   │
│ ---     ┆ ---                        ┆ ---           ┆ ---                                            │
│ i64     ┆ str                        ┆ i64           ┆ str                                            │
╞═════════╪════════════════════════════╪═══════════════╪════════════════════════════════════════════════╡
│ 120     ┆ 2024-02-02 00:01:00.001+00 ┆ 1020240202450 ┆ {"amount":10000,"currency":"NZD","seqnbr":850} │
│ 121     ┆ 2024-02-02 00:02:00.001+00 ┆ 1020240202451 ┆ {"amount":20000,"currency":"AUD","seqnbr":841} │
│ 122     ┆ 2024-02-02 00:03:00.001+00 ┆ 1020240202452 ┆ {"amount":30000,"currency":"USD","seqnbr":null}│
│ 123     ┆ 2024-02-02 00:04:00.001+00 ┆ 1020240202455 ┆ {"amount":40000,"currency":"INR","seqnbr":937} │
└─────────┴────────────────────────────┴───────────────┴────────────────────────────────────────────────┘

Хороший! Я думаю, что случайное число также можно записать с помощью выражения: pl.int_range(500, 999).sample(pl.len())

jqurious 03.07.2024 14:21

спасибо, не подумал sample, добавлю в ответ

Roman Pekar 03.07.2024 14:28
Ответ принят как подходящий

Я внес несколько изменений в ваш код, используя csv для написания нового csv, и, самое главное, удалил ту часть write, которая игнорировала строки None:

def update_seqnbr(cls):
    filename = 'input.csv'
    seqnbr_pattern = "'seqnbr': ([\s\d]+)"
    with open(FILENAME, 'a', newline='') as targetfile:
        targetcsv = csv.writer(targetfile, delimiter='|')
        with open(filename, 'r') as csvfile:
            datareader = (csv.reader(csvfile, delimiter = "|"))
            targetcsv.writerow(next(datareader, None))  # skip the headers
            for row in datareader:
                json_message = row[3]
                match = re.findall(seqnbr_pattern, json_message)
                if len(match) != 0:
                    replaced_json_message = json_message.replace(match[0], str(random.randint(500, 999)))
                    row[3] = replaced_json_message
                targetcsv.writerow(row)

Вот результат:

row_num|start_date_time|id|json_message
120|2024-02-02 00:01:00.001+00|1020240202450|{'amount': 10000, 'currency': 'NZD','seqnbr': 961}
121|2024-02-02 00:02:00.001+00|1020240202450|{'amount': 20000, 'currency': 'NZD','seqnbr': 863}
122|2024-02-02 00:03:00.001+00|1020240202450|{'amount': 30000, 'currency': 'NZD','seqnbr': None }
123|2024-02-02 00:04:00.001+00|1020240202450|{'amount': 40000, 'currency': 'NZD','seqnbr': 666}

Я попробовал это, и происходит то, что к исходному файлу добавляются новые строки, содержащие обновленное значение для seqnbr, и он работает в бесконечном цикле с одним и тем же набором исходных записей, копируемых снова и снова с новыми значениями.

Balaji Venkatachalam 03.07.2024 20:36

Он отлично работает, если я изменю файловый режим с «a» на «r+» для целевого файла. Спасибо огромное

Balaji Venkatachalam 03.07.2024 21:57

Ой, извините, но я filename и FILENAME указали на два разных файла (например, input.csv и output.csv). Рад, что вам удалось его адаптировать.

Swifty 04.07.2024 11:01

В полярах Python этого можно добиться следующим образом.

  1. Используйте pl.Expr.str.json_decode, чтобы преобразовать столбец json_message в столбец struct с одним полем для каждого поля JSON.
  2. Используйте конструкцию pl.when().then(), чтобы условно заменить поле "seqnbr" в столбце структуры случайным целым числом.
  3. Используйте pl.Expr.struct.json_encode, чтобы преобразовать столбец struct обратно в столбец строк JSON.
import numpy as np

(
    df
    # convert json_message to struct column
    .with_columns(pl.col("json_message").str.json_decode())
    # conditionally replace seqnbr values
    .with_columns(
        pl.col("json_message").struct.with_fields(
            pl.when(
                pl.field("seqnbr").is_not_null()
            ).then(
                np.random.randint(0, 200, size=df.height)
            ).alias("seqnbr")
        )
    )
    # convert json_message to json string
    .with_columns(
        pl.col("json_message").struct.json_encode()
    )
)
shape: (4, 4)
┌─────────┬─────────────────────────┬───────────────┬─────────────────────────────────────────────────┐
│ row_num ┆ start_date_time         ┆ id            ┆ json_message                                    │
│ ---     ┆ ---                     ┆ ---           ┆ ---                                             │
│ i64     ┆ datetime[μs]            ┆ str           ┆ str                                             │
╞═════════╪═════════════════════════╪═══════════════╪═════════════════════════════════════════════════╡
│ 120     ┆ 2024-02-02 00:01:00.001 ┆ 1020240202450 ┆ {"amount":10000,"currency":"NZD","seqnbr":108}  │
│ 121     ┆ 2024-02-02 00:02:00.001 ┆ 1020240202451 ┆ {"amount":20000,"currency":"AUD","seqnbr":133}  │
│ 122     ┆ 2024-02-02 00:03:00.001 ┆ 1020240202452 ┆ {"amount":30000,"currency":"USD","seqnbr":null} │
│ 123     ┆ 2024-02-02 00:04:00.001 ┆ 1020240202455 ┆ {"amount":40000,"currency":"INR","seqnbr":43}   │
└─────────┴─────────────────────────┴───────────────┴─────────────────────────────────────────────────┘

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

Как создать иерархическую карту цветов в matplotlib?
Расширенная логика с группировкой, применением и преобразованием - сравнение значения строки с предыдущим значением и создание нового столбца
Каков самый быстрый способ расчета ежедневного баланса со сложными процентами в Pandas или Spark?
Я выбрал два столбца в объекте groupby. Как применить фильтр true или false к одному, а затем применить функцию к другому?
Выявляйте и отмечайте дубликаты, каждый из которых имеет определенное качество
Чтение CSV-файла с помощью Pandas в рабочей области Databricks
Применить функцию к двум столбцам pandas и назначить их обратно исходному фрейму данных, что вызовет предупреждение в будущем
Странное поведение при обновлении значений с использованием iloc в фрейме данных pandas
Как это описание понимается в документации pandas?
Суммирование строк в DataFrame Pandas, где количество суммируемых строк основано на значениях столбцов в другом DataFrame