Вопрос или проблема
У меня есть CSV-файл с примерно 50 столбцами и от 20 до 100 строк.
Отдельные записи имеют идентификаторы, и некоторые записи могут быть в группе по 2. По сути, мне нужно добавить идентификатор в ту же строку, где находится другой идентификатор из этой группы. Пример:
ID ,group,blank column
2019-1 , ,
2019-2 ,GRP1 ,
2019-3 ,GRP2 ,
2019-4 ,GRP1 ,
2019-5 , ,
2019-6 ,GRP2 ,
А на выходе я бы хотел получить:
ID ,group,blank column
2019-1 , ,
2019-2 ,GRP1 ,2019-4
2019-3 ,GRP2 ,2019-6
2019-5 , ,
В моих попытках использовать awk, мне не удалось добиться успеха. Я либо оставляю строки без группы, либо в итоге повторяю значения.
perl -a -F, -ne 'if($F[1]=~/\S/) { push @{$d{$F[1]}}, $F[0]; } else { print ; }
END {
for(keys %d){
print shift @{$d{$_}},",$_, ",@{$d{$_}},"\n"
}
}' my.csv
Следующий код перепишет поле ID
в виде списка значений ID
, разделенных ;
, для которых остальные поля совпадают. Он также очищает пробелы.
$ mlr --csv clean-whitespace then nest --ivar ';' -f ID file
ID,group,blank column
2019-1;2019-5,,
2019-2;2019-4,GRP1,
2019-3;2019-6,GRP2,
Это не совсем то, что вы хотели, но дает вам своего рода преобразование, которое вы показали в вопросе.
Добавление дополнительной строки с GRP1
:
$ cat file
ID ,group,blank column
2019-1 , ,
2019-2 ,GRP1 ,
2019-3 ,GRP2 ,
2019-4 ,GRP1 ,
2019-5 , ,
2019-6 ,GRP2 ,
2025-3 ,GRP1 ,
$ mlr --csv clean-whitespace then nest --ivar ';' -f ID file
ID,group,blank column
2019-1;2019-5,,
2019-2;2019-4;2025-3,GRP1,
2019-3;2019-6,GRP2,
Ответ или решение
Задача обработки CSV-файлов, как описано, является типичным примером задачи по манипуляции данных, где необходимо преобразовать данные исходного файла в более удобочитаемый и информативный вид. В данном случае мы имеем набор записей с идентификаторами (ID) и группами, и наша задача заключается в том, чтобы объеденить связанные записи на основании их групп. Поскольку некоторые записи сгруппированы парами, нам нужно сохранить информацию об этих отношениях, добавляя идентификатор второй записи в соответствующую строку первой записи группы.
Теория:
В основе задачи лежит концепция манипуляции строками и колонками в файле CSV на базе определённого условия. CSV (Comma-Separated Values) — это текстовый формат, используемый для хранения табличных данных, таких как электронные таблицы или базы данных. Каждая строка в таком файле обычно представляет одну запись, а данные в строке разделены запятыми (или другим разделителем).
В данном случае, группировка данных проводится по наличию значения в колонке "group". Если значение присутствует, это указывает на то, что строки с одинаковой группой должны быть связаны между собой. Наша цель — модифицировать запись (строку) таким образом, чтобы на месте пустого столбца появлялся идентификатор другой записи из той же группы.
Пример:
Давайте рассмотрим исходный набор данных:
ID ,group,blank column
2019-1 , ,
2019-2 ,GRP1 ,
2019-3 ,GRP2 ,
2019-4 ,GRP1 ,
2019-5 , ,
2019-6 ,GRP2 ,
Требуется, чтобы результирующий набор данных выглядел следующим образом:
ID ,group,blank column
2019-1 , ,
2019-2 ,GRP1 ,2019-4
2019-3 ,GRP2 ,2019-6
2019-5 , ,
Структурируя так, чтобы каждая строка, принадлежащая группе, содержала в пустой колонке идентификатор другой записи из этой же группы.
Применение:
Для реализации данной задачи можно воспользоваться несколькими подходами. Один из них нам был предложен использовал Perl, однако он может оказаться сложным в использовании для непосвященных. Другим вариантом является использование специальных утилит для работы с CSV, таких как Miller (mlr), которая позволяет выполнять сложные трансформации с данными в CSV-формате.
Основная идея заключается в использовании словаря или хэша для хранения групп и связанных с ними идентификаторов. Сначала мы считываем весь CSV-файл, после чего проходим по каждой записи и распределяем идентификаторы по группам с использованием словаря. Затем, после завершения первого прохода, мы создаём результирующий набор данных, преобразовывая данные в новый формат.
Этапы решения:
- Чтение данных из CSV и инициализация структуры данных для хранения групп:
- Создать словарь, где ключом будет выступать название группы, а значением — список идентификаторов, попадающих в эту группу.
- Перебирать строки CSV, и для каждой группы добавлять идентификатор в соответствующий список.
- После того, как все данные были распределены, пройти по портированному словарю групп, и добавить второй идентификатор из каждой группы в строку первой записи группы.
- Построить новый CSV на основе полученных данных.
Также можно автоматизировать процесс с помощью языков программирования, таких как Python, который предоставляет библиотеку csv
для работы с файлами CSV, что позволяет выполнять подобные манипуляции относительно легко и эффективно.
Пример на Python может выглядеть следующим образом:
import csv
def process_csv(input_file, output_file):
with open(input_file, mode='r', newline='') as infile:
reader = csv.DictReader(infile)
rows = list(reader)
groups = {}
for row in rows:
group = row['group'].strip()
if group:
if group not in groups:
groups[group] = []
groups[group].append(row['ID'].strip())
for row in rows:
group = row['group'].strip()
if group and len(groups[group]) > 1:
row['blank column'] = groups[group][1]
else:
row['blank column'] = ''
with open(output_file, mode='w', newline='') as outfile:
writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames)
writer.writeheader()
writer.writerows(rows)
process_csv('input.csv', 'output.csv')
Этот скрипт позволит вам выполнить всю необходимую работу с CSV-файлом, уделяя внимание чистоте и аккуратности кода. Такой подход прост для понимания, не требует дополнительного программного обеспечения, кроме установленного Python, и легко поддается модификации для решения более сложных задач обработки данных.