Обработка CSV: перемещение значения столбца/строки в другую строку, где значение столбца совпадает.

Вопрос или проблема

У меня есть 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-файл, после чего проходим по каждой записи и распределяем идентификаторы по группам с использованием словаря. Затем, после завершения первого прохода, мы создаём результирующий набор данных, преобразовывая данные в новый формат.

Этапы решения:

  1. Чтение данных из CSV и инициализация структуры данных для хранения групп:
    • Создать словарь, где ключом будет выступать название группы, а значением — список идентификаторов, попадающих в эту группу.
  2. Перебирать строки CSV, и для каждой группы добавлять идентификатор в соответствующий список.
  3. После того, как все данные были распределены, пройти по портированному словарю групп, и добавить второй идентификатор из каждой группы в строку первой записи группы.
  4. Построить новый 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, и легко поддается модификации для решения более сложных задач обработки данных.

Оцените материал
Добавить комментарий

Капча загружается...