В этом сообщении блога мы углубимся в процесс сравнения двух файлов CSV с использованием Python и создания отдельного файла CSV, в котором будут отражены различия между ними.
Ссылка на GitHub — https://github.com/satsundev/compare-csv
Прежде чем мы отправимся в это путешествие, важно убедиться, что Python (https://www.python.org/downloads/) установлен на вашем компьютере.
Поскольку наши предстоящие задачи связаны с обработкой файлов, наличие в нашем распоряжении библиотеки Pandas имеет первостепенное значение. Pandas обеспечивает беспрепятственное взаимодействие с файлами CSV, облегчая обработку и манипулирование данными. Обязательно установите библиотеку Pandas, используя следующую команду:
Давайте создадим новый файл с именем compare.py
и импортируем необходимые библиотеки: Pandas, os, json и sys. Это подготовит почву для процесса сравнения файлов CSV.
Чтобы облегчить множественное сравнение, мы можем создать входную конфигурацию, используя файл JSON. Этот подход позволит нам легко предоставлять входные данные и получать доступ к значениям. Давайте создадим новый файл с именем input.json внутри папки с именем data.
Шаг 1. Проверка существования файла
Прежде чем отправиться в путешествие, крайне важно проверить наличие необходимых файлов CSV. Эти файлы содержат ожидаемые и фактические данные для сравнения. Если какой-либо файл отсутствует, наши усилия корректно прекратятся.
# get the current working directory cwd = os.getcwd() # get the input JSON file. input_JSON = os.path.join(cwd, "data", "input.json") # load the JSON file into a variable input_data = json.load(open(input_JSON)) # get the data object from input_data variable # if we need we can also ensure the node is available data = input_data["info"] for info in data: print("Summary: " + info["description"]) # get the expected JSON file expected = os.path.join(cwd, "inputs" ,"expected" ,info["expected"]) # get the actual JSON file actual = os.path.join(cwd, "inputs", "actual" ,info["actual"]) # diff path diff = os.path.join(cwd, "inputs", "diff" ,info["diff"]) # summary path summary = os.path.join(cwd, "inputs", "diff", info["summary"]) # common identity column with unique value between two CSV files to compare identity = info["identity"] # check the actual and expected CSV files are present # if not present intimate not present and stop execution if(not os.path.exists(expected) and not os.path.exists(actual)): # we can modify the custom message as needed print("## file in expected or actual path not present") sys.exit(0)
Шаг 2. Преобразование и сортировка данных
Подготовив файлы, мы переключаем внимание на преобразование данных и выполнение сравнения. Наша первая задача — отсортировать столбцы как ожидаемых, так и фактических наборов данных, чтобы обеспечить плавное выравнивание столбцов.
else: # read the expected, actual CSV file expected_CSV = pd.read_csv(expected, encoding="utf-8") actual_CSV = pd.read_csv(actual, encoding="utf-8") # sort the expected file and actual file with same axis expected_CSV = expected_CSV.sort_index(axis=1) actual_CSV = actual_CSV.sort_index(axis=1)
Шаг 3: Объединение и сравнение данных
Теперь наш путь ведет нас к конвергенции данных посредством операции слияния кадров данных Pandas. Важным аспектом является указание столбцов идентификаторов как для ожидаемых, так и для фактических наборов данных, что обеспечивает значимое и точное объединение.
expected_CSV_col = list(expected_CSV) # add suffix _expected for all expected column names expected_CSV_sfx = expected_CSV.add_suffix("_expected") # add suffix _actual for all actual column names actual_CSV_sfx = actual_CSV.add_suffix("_actual") # Outer Join expected and actual csv with identity comparision = pd.merge(expected_CSV_sfx, actual_CSV_sfx, how="outer", left_on=identity + "_expected", right_on=identity + "_actual") # create new column for every expected column with suffix '_compare' # compare each column and update the value comparision to '_compare' column for col in expected_CSV_col: comparision[(col + "_#compare")] = comparision[(col + "_actual")].fillna("-") == comparision[(col + "_expected")].fillna("-")
Шаг 4. Запишите разницу в формате CSV.
Наше путешествие завершается сохранением результатов сравнения данных. Кульминация наших усилий увековечена в новом файле CSV — артефакте, который отражает сложный танец между ожидаемыми и фактическими данными.
# reorder the columns comparision = comparision.reindex(sorted(comparision.columns), axis=1) # write as CSV into diff folder comparision.to_csv(diff)
Шаг 5: Результат — CSV различий
Напомним весь код:
данные/input.json
{ "info": [{ "description": "This CSV file contains information about users present in an company.", "expected": "user_info_expected.csv", "actual": "user_info_actual.csv", "diff": "user_info_diff.csv", "summary": "user_info_summary.csv", "identity": "id" }] }
сравнить.py
import pandas as pd import os import json import sys # get the current working directory cwd = os.getcwd() # get the input JSON file. input_JSON = os.path.join(cwd, "data", "input.json") # load the JSON file into a variable input_data = json.load(open(input_JSON)) # get the data object from input_data variable # if we need we can also ensure the node is available data = input_data["info"] for info in data: print("Summary: " + info["description"]) # get the expected JSON file expected = os.path.join(cwd, "inputs" ,"expected" ,info["expected"]) # get the actual JSON file actual = os.path.join(cwd, "inputs", "actual" ,info["actual"]) # diff path diff = os.path.join(cwd, "inputs", "diff" ,info["diff"]) # summary path summary = os.path.join(cwd, "inputs", "diff", info["summary"]) # common identity column with unique value between two CSV files to compare identity = info["identity"] # check the actual and expected CSV files are present # if not present intimate not present and stop execution if(not os.path.exists(expected) and not os.path.exists(actual)): # we can modify the custom message as needed print("## file in expected or actual path not present") sys.exit(0) else: # read the expected, actual CSV file expected_CSV = pd.read_csv(expected, encoding="utf-8") actual_CSV = pd.read_csv(actual, encoding="utf-8") # sort the expected file and actual file with same axis expected_CSV = expected_CSV.sort_index(axis=1) actual_CSV = actual_CSV.sort_index(axis=1) # get all the expected column names as list expected_CSV_col = list(expected_CSV) # add suffix _expected for all expected column names expected_CSV_sfx = expected_CSV.add_suffix("_expected") # add suffix _actual for all actual column names actual_CSV_sfx = actual_CSV.add_suffix("_actual") # Outer Join expected and actual csv with identity comparision = pd.merge(expected_CSV_sfx, actual_CSV_sfx, how="outer", left_on=identity + "_expected", right_on=identity + "_actual") # create new column for every expected column with suffix '_compare' # compare each column and update the value comparision to '_compare' column for col in expected_CSV_col: comparision[(col + "_#compare")] = comparision[(col + "_actual")].fillna("-") == comparision[(col + "_expected")].fillna("-") # reorder the columns comparision = comparision.reindex(sorted(comparision.columns), axis=1) # write as CSV into diff folder comparision.to_csv(diff)
Надеюсь это поможет :)
Весь этот процесс, от проверки файлов до сравнения и сохранения данных, осуществляется посредством тщательно продуманной оркестровки магии Python и Pandas. Результатом является комплексный снимок различий в данных, который можно просмотреть, проанализировать и использовать для принятия обоснованных решений.