Как объединить два CSV-файла?

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

Предположим, у вас есть один CSV-файл с 2 полями: ID и email. У вас есть другой файл с 2 полями: email и имя. Как вы можете создать файл со всеми тремя полями, объединенными по email?

Revision3:

Вы должны отсортировать оба списка по email в алфавитном порядке, а затем объединить. Поскольку поле email является 2-м полем первого файла и 1-м полем второго файла:

sort -t , -k 2,2 file1.csv > sort1.csv
sort -t , -k 1,1 file2.csv > sort2.csv
join -t , -1 2 -2 1 sort1.csv sort2.csv > sort3.csv

значения параметров

-t ,   : ',' является разделителем полей
-k 2,2 : сортировка по 2-му полю
-k 1,1 : сортировка по 1-му полю
-1 2   : файл 1, 2-е поле
-2 1   : файл 2, 1-е поле
>      : вывод в файл

получается

email,ID,name
email,ID,name
...

отсортированных по email в алфавитном порядке.

Обратите внимание, что если какой-либо email отсутствует в любом из файлов, он будет исключён из результатов.

Используйте csvkit:

csvjoin -c email id_email.csv email_name.csv

или

csvjoin -c 2,1 id_email.csv email_name.csv

Возможно, это избыточно, но вы можете импортировать в базу данных
(например, OpenOffice Base) как два типа таблиц и определить
отчет, который будет необходимым выводом.

Если импорт CSV является проблемой, программа для работы с таблицами
(например, OpenOffice Calc) может выполнить импорт. Результат можно
легко передать в базу данных.

На будущее, вы могли бы начать пробовать AWK. Это очень простой язык сценариев, который существует в какой-то форме на каждой системе *nix, и его единственная цель — манипуляция текстовыми базами данных с разделителями. С небольшим количеством одноразового скрипта вы можете сделать некоторые очень полезные вещи. Язык небольшой и элегантный и имеет лучшее соотношение утилита/сложность, чем что-либо еще, о чем я знаю.

Используйте Go: https://github.com/chrislusf/gleam

package main

import (
    "flag"
    "os"

    "github.com/chrislusf/gleam"
    "github.com/chrislusf/gleam/source/csv"
)

var (
    aFile = flag.String("a", "a.csv", "первый csv файл с 2 полями, первым из которых является ключ")
    bFile = flag.String("b", "b.csv", "второй csv файл с 2 полями, первым из которых является ключ")
)

func main() {

    flag.Parse()

    f := gleam.New()
    a := f.Input(csv.New(*aFile))
    b := f.Input(csv.New(*bFile))

    a.Join(b).Fprintf(os.Stdout, "%s,%s,%s\n").Run()

}

Вы также можете прочитать CSV файл с помощью программы для работы с таблицами, такой как LibreOffice, и использовать макрос VLOOKUP() для поиска имени во втором файле.

В Bash 5.0.3 с GNU Coreutils 8.30 и ссылаясь на ответ hyperslug:

Если у вас есть неотсортированные CSV файлы с дублирующимися строками и вы не хотите пропускать данные из-за отсутствующего поля в строке любого из file1.csv или file2.csv, то вы можете сделать следующее:

Отсортируйте файл 1 по полю 2 и файл 2 по полю 1:

( head -n1 file1.csv && tail -n+2 file1.csv | sort -t, -k2,2 ) > sort1.csv
( head -n1 file2.csv && tail -n+2 file2.csv | sort -t, -k1,1 ) > sort2.csv

Расширяя параметры hyperslug:

-k 2,2     : сортировка символов, начинающаяся и заканчивающаяся на 2-м поле
-k 1,1     : сортировка символов, начинающаяся и заканчивающаяся на 1-м поле
head -n1   : считать первую строку
tail -n+1: : считать все, кроме первой строки
(  )       : подсеть
>          : вывод в файл

Мне нужно было использовать head и tail внутри подсети ( ), чтобы сохранить первую строку заголовка CSV файла при сортировке по данному полю.

Затем,

join -t , -a1 -a2 -1 2 -2 1 -o auto sort1.csv sort2.csv > sort3.csv

Расширяя параметры hyperslug:

-t ,    : ',' является разделителем полей
-a1     : Не пропускайте строки из файла 1, если совпадение в файле 2 не найдено
-a2     : Не пропускайте строки из файла 2, если совпадение в файле 1 не найдено.
-1 2    : файл 1, 2-е поле
-2 1    : файл 2, 1-е поле
-o auto : Автоформат: включает дополнительные запятые, указывающие на несовпадающие поля
>       : вывод в файл

Вот пример file1.csv, file2.csv и результирующего sort3.csv:

file1.csv:

ID,email
02,[email protected]
03,[email protected]
05,[email protected]
07,[email protected]
11,[email protected]

file2.csv:

email,name
[email protected],Timothy Brown
[email protected],Robert Green
[email protected],Raul Vasquez
[email protected],Carol Lindsey

sort3.csv:

email,ID,name
[email protected],02,Robert Green
[email protected],,Carol Lindsey
[email protected],03,
[email protected],07,Raul Vasquez
[email protected],05,
[email protected],,Timothy Brown
[email protected],11,

Вы можете увидеть, что у Timothy Brown и Carol Lindsey отсутствуют ID, но они все равно включены в объединенный CSV файл (с их именами и email в правильных полях).

Попробуйте CSV Cruncher.

Он принимает CSV файлы в качестве SQL таблиц и затем позволяет выполнять SQL запросы, в результате чего создается другой CSV или JSON файл.

Для вашего случая вы просто вызовете:

crunch -in tableA.csv -in tableB.csv
   -out output.csv
   -sql "SELECT tableA.id, tableA.email, tableB.name 
    FROM tableA LEFT JOIN tableB USING (email)"

Инструмент требует Java 11 или более поздней версии.

Некоторые из преимуществ:

  • Вы действительно получаете поддержку CSV, а не просто “давайте предположим, что данные верны”.
  • Вы можете объединять по нескольким ключам.
  • Проще использовать и понимать, чем решения на основе join.
  • Вы можете объединить более 2 CSV файлов.
  • Вы можете объединять по SQL выражениям – значения не обязательно должны быть одинаковыми.

Отказ от ответственности: Я написал этот инструмент.

Вы также можете использовать инструмент, специально разработанный для объединения csv файлов, такой как тот, который находится на https://filerefinery.com

Операции, которые мы в настоящее время поддерживаем: Объединение csv файлов. Возможен SQL-эквивалент внешних, внутренних, левых и правых операций соединения на двух csv файлах. Какой столбец будет использоваться в качестве ключа объединения в каждом из файлов, настраивается.

Ответ или решение

Объединение двух CSV файлов – это распространённая задача при работе с данными. Допустим, у вас есть два файла, один с полями ID и email, а другой с полями email и name. В данной статье мы рассмотрим, как объединить эти файлы по полю email, чтобы получить новый файл с тремя полями: email, ID и name.

Шаг 1: Подготовка файлов

Перед тем как начать объединение, важно отсортировать оба файла по полю email. Это необходимо, поскольку команда объединения (join) требует, чтобы файлы были отсортированы.

Воспользуемся командной строкой для сортировки:

sort -t , -k 2,2 file1.csv > sort1.csv
sort -t , -k 1,1 file2.csv > sort2.csv
  • -t , указывает на то, что разделителем является запятая.
  • -k 2,2 обозначает, что сортировка будет проходить по второму полю для первого файла.
  • -k 1,1 – для второго файла по первому полю.

Таким образом, у нас получится два отсортированных файла: sort1.csv и sort2.csv.

Шаг 2: Объединение файлов

Теперь можно объединить два отсортированных файла по полю email. Для этого используем команду join:

join -t , -1 2 -2 1 sort1.csv sort2.csv > result.csv
  • -1 2 указывает, что в первом файле нужно взять второе поле (email).
  • -2 1 указывает на то, что во втором файле нужно взять первое поле (email).
  • > result.csv направляет вывод в новый файл.

Шаг 3: Обработка отсутствующих данных

В случае, если необходимо оставить все записи из обоих файлов, даже если у одной из записей нет соответствующей записи в другом файле, вы можете использовать параметры -a1 и -a2:

join -t , -a1 -a2 -1 2 -2 1 -o auto sort1.csv sort2.csv > result.csv

Этот вариант объединения позволит сохранить все данные и избежать потери информации, если для некоторых email не найдется соответствующих записей.

Альтернативные методы

  1. Использование csvkit:
    Если вы предпочитаете работать с более высокоуровневыми инструментами, используйте csvkit. Эта библиотека Python предоставляет инструменты для работы с CSV файлами:

    csvjoin -c email id_email.csv email_name.csv > result.csv
  2. Базы данных:
    Для более сложных сценариев можно импортировать данные в реляционную базу данных и использовать SQL-запросы для объединения данных. Это может быть выполнено через такие инструменты, как OpenOffice Base или другие СУБД.

  3. Программирование:
    Если вы предпочитаете программировать, можно использовать язык Go с библиотекой gleam для выполнения объединений CSV:

    package main
    
    import (
       "flag"
       "os"
       "github.com/chrislusf/gleam"
       "github.com/chrislusf/gleam/source/csv"
    )
    
    var (
       aFile = flag.String("a", "a.csv", "первый csv файл")
       bFile = flag.String("b", "b.csv", "второй csv файл")
    )
    
    func main() {
       flag.Parse()
       f := gleam.New()
       a := f.Input(csv.New(*aFile))
       b := f.Input(csv.New(*bFile))
       a.Join(b).Fprintf(os.Stdout, "%s,%s,%s\n").Run()
    }

Заключение

Объединение CSV файлов может быть выполнено различными методами: от командной строки до программных решений. Выбор метода зависит от объема данных, ваших предпочтений и доступных инструментов. С помощью описанных выше шагов и инструментов вы сможете успешно объединить два CSV файла по полю email, создавая новый файл, содержащий всю необходимую информацию.

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

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