У меня есть файл CSV с именем input.csv
и следующими столбцами:
Я использую 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()
Ниже показано, как должен выглядеть мой файл:
Может кто-нибудь помочь мне с этим?
@jqurious, это репродукция Python. Чтобы сделать это действительным JSON, мы затем используем json_string = (col[3]).replace("'", '"') и передаем Jsonb(eval(json_string)) в нашем SQL-запросе.
seqnbr
поля.#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())
спасибо, не подумал sample
, добавлю в ответ
Я внес несколько изменений в ваш код, используя 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, и он работает в бесконечном цикле с одним и тем же набором исходных записей, копируемых снова и снова с новыми значениями.
Он отлично работает, если я изменю файловый режим с «a» на «r+» для целевого файла. Спасибо огромное
Ой, извините, но я filename
и FILENAME
указали на два разных файла (например, input.csv и output.csv). Рад, что вам удалось его адаптировать.
В полярах Python этого можно добиться следующим образом.
json_message
в столбец struct
с одним полем для каждого поля JSON.pl.when().then()
, чтобы условно заменить поле "seqnbr"
в столбце структуры случайным целым числом.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} │
└─────────┴─────────────────────────┴───────────────┴─────────────────────────────────────────────────┘
Однако в этом примере json_message не является допустимым JSON — это текст Python «repr». У вас действительно есть необработанные данные JSON или нет?