У меня есть 2 CSV, которые выглядят так:
input.csv
:
search.csv
:
Я хочу использовать значение (sku
) из search.csv
для поиска совпадения в input.csv
и, если совпадение будет найдено, оно должно добавить соответствующее значение из cost_production
в столбец cost_production
в input.csv
и вывести его в новый файл.
Вот что у меня есть на данный момент:
import csv
ID, SKU, COSTS_PRODUCTION = 'id', 'sku', 'costs_production' # Field names referenced.
# Read entire input file into a list.
with open('input.csv', 'r', newline='') as inp:
reader = csv.DictReader(inp)
inputs = list(reader)
# Update input rows that match data in search.csv file.
with open('search.csv', 'r', newline='') as sea:
sea_reader = csv.DictReader(sea)
for row in sea_reader:
SKU, COSTS_PRODUCTION = row[SKU], row[COSTS_PRODUCTION]
for input_ in inputs:
if input_[SKU] == SKU: # Match?
input_[COSTS_PRODUCTION] = row[COSTS_PRODUCTION]
break
# Write updated input.csv data out into a file.
with open('input_updated.csv', 'w', newline='') as outp:
fieldnames = inputs[0].keys()
writer = csv.DictWriter(outp, fieldnames)
writer.writeheader()
writer.writerows(inputs)
print('done')
Я продолжаю получать KeyError: 'h01'
.
Обратите внимание, что форматирование таблицы менее полезно, чем реальный файл CSV, который люди могут скопировать и вставить. Или, если предположить, что проблема заключается не столько в записи и чтении файлов, сколько в промежуточной обработке данных, полностью вырежьте файлы и покажите список словарей - приведите минимальный воспроизводимый пример.
Было бы проще, если бы вы рассмотрели возможность использования dataframe
в pandas
.
Например:
import pandas as pd
input_df = pd.read_csv('input.csv')
search_df = pd.read_csv('search.csv')
merged_df = pd.merge(input_df, search_df, on='sku', how='left')
# Fill the costs_production column with the corresponding values from search.csv
merged_df['costs_production'] = merged_df['costs_production_y'].fillna(merged_df['costs_production_x'])
merged_df = merged_df[['id', 'sku', 'costs_production']]
merged_df.to_csv('input_updated.csv', index=False)
Однако, если вы все еще рассматриваете возможность использования csv
, проблема возникает из-за того, что переменные, содержащие ключи столбцов (SKU
и COSTS_PRODUCTION
), и переменные, содержащие фактические значения из строк CSV, имеют одинаковые имена. В частности, следующая строка вызывает проблему:
SKU, COSTS_PRODUCTION = row[SKU], row[COSTS_PRODUCTION]
Чтобы решить эту проблему, присвойте значения CSV переменным с уникальными именами, например:
# Update input rows that match data in search.csv file.
with open('search.csv', 'r', newline='') as sea:
sea_reader = csv.DictReader(sea)
for row in sea_reader:
search_sku = row[SKU]
search_costs_production = row[COSTS_PRODUCTION]
for input_ in inputs:
if input_[SKU] == search_sku:
input_[COSTS_PRODUCTION] = search_costs_production
break
С помощью JayPeerachai я немного поигрался, снова отфильтровал результаты и получил вот это как окончательное решение.
Возможно, это поможет некоторым из вас.
# Update input rows that match data in search.csv file.
with open('search.csv', 'r', newline='') as sea:
sea_reader = csv.DictReader(sea)
for row in sea_reader:
# SKU, COSTS_PRODUCTION = row[SKU], row[COSTS_PRODUCTION]
# SKU = row[SKU]
for input_ in inputs:
# if input_[SKU] == SKU: # Match?
if input_['sku'] == row[SKU]:
try:
input_[COSTS_PRODUCTION] = row[COSTS_PRODUCTION]
except KeyError:
import ipdb ; ipdb.set_trace()
break
filtered_inputs = [entry for entry in inputs if entry[COSTS_PRODUCTION] != '']
к вашему сведению: возможно, на DuckDB стоит посмотреть
import os
import tempfile
import duckdb
tmpDB=tempfile.NamedTemporaryFile().name
con = duckdb.connect(tmpDB)
con.sql("create table input as select * from read_csv( 'input.csv')")
con.sql("create table search as select * from read_csv( 'search.csv')")
con.sql("COPY (select input.id, input.sku, search.costs_production from input,search where input.sku = search.sku) TO 'input-updated.csv' (HEADER,DELIMITER '\t') ")
os.unlink(tmpDB)
#produces
id sku costs_production
12 h01 14.95
13 h02 51.99
Пожалуйста, рассмотрите возможность исправления отступов. Также включите полную ошибку трассировки.