Объединение CSV в Bash, когда ключ в одной таблице используется несколько раз - PullRequest
0 голосов
/ 05 августа 2020

У меня есть csv, в котором идентификатор появляется несколько раз, и другой csv с информацией об этом идентификаторе. Я хотел бы добавить столбцы во втором csv к первому для каждой строки.

data1.csv
+---+---------------------+--------+
| ID| DATE                | AMOUNT |
+---+---------------------+--------+
| 1 | 2019-09-08 00:00:00 |   3000 |
| 1 | 2019-10-08 00:00:00 |   1500 |
| 1 | 2019-11-20 00:00:00 |   1560 |
| 2 | 2008-05-20 00:00:00 |   2060 |
+-----+---------------------+------+

data2.csv
+----+----------+-----+-----------+
| ID | NAME     | AGE | Location  | 
+----+----------+-----+-----------+
|  1 | J. Smith |  32 | New York  |
|  2 | A. Jones |  25 | Chicago   |
+----+----------+-----+-----------+

Я хотел бы создать

+---+---------------------+--------+----------+-----+-----------+
| ID| DATE                | AMOUNT | NAME     | AGE | Location  | 
+---+---------------------+--------+----------+-----+-----------+
| 1 | 2019-09-08 00:00:00 |   3000 | J. Smith |  32 | New York  |
| 1 | 2019-10-08 00:00:00 |   1500 | J. Smith |  32 | New York  |
| 1 | 2019-11-20 00:00:00 |   1560 | J. Smith |  32 | New York  |
| 2 | 2008-05-20 00:00:00 |   2060 | A. Jones |  25 | Chicago   |
+-----+---------------------+------+----------+-----+-----------+

Я пытаюсь сделать это в нативном bash, если это все возможно - некоторые пользователи будут использовать Cygwin в Windows, и пытаться запустить Python будет беспорядком, если он у них не настроен правильно. Обычно я бы просто использовал Pandas.

До сих пор все, что мне удалось найти, предполагает, что CSV можно отсортировать и сопоставить каждый из них. Я могу представить себе создание al oop, который просматривает каждый идентификатор в data1 и ищет его в data2, а затем объединяет их с помощью awk, но этот набор данных будет иметь много повторов, и кажется, что это был бы действительно неэффективный способ go об этом.

Похоже, что должен существовать способ выполнить левое соединение для повторяемого ключа, но я ничего не вижу. Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

2 голосов
/ 05 августа 2020

Решение оболочки будет медленным для большого набора данных / файлов, но вот оно.

data1.csv и его содержимое

ID,DATE,AMOUNT
1,2019-09-08 00:00:00,3000
1,2019-10-08 00:00:00,1500
1,2019-11-20 00:00:00,1560
2,2008-05-20 00:00:00,2060

data2.csv и его содержимое

ID,NAME,AGE,Location
1,J. Smith,32,New York
2,A. Jones,25,Chicago

Скрипт.

#!/usr/bin/env bash

IFS= read -r data1_head < data1.csv
IFS= read -r data2_head < data2.csv
printf '%s,%s\n' "$data1_head" "${data2_head#*,}"

while IFS= read -ru8 data1; do
  while IFS= read -ru9 data2; do
    if [[ "${data1%%,*}" == "${data2%%,*}" ]]; then
      printf '%s,%s\n' "$data1" "${data2#*,}"
    fi
  done 9< <(tail -n+2 data2.csv)
done 8< <(tail -n+2 data1.csv)

Выход

ID,DATE,AMOUNT,NAME,AGE,Location
1,2019-09-08 00:00:00,3000,J. Smith,32,New York
1,2019-10-08 00:00:00,1500,J. Smith,32,New York
1,2019-11-20 00:00:00,1560,J. Smith,32,New York
2,2008-05-20 00:00:00,2060,A. Jones,25,Chicago

Если ed доступен / приемлем, предполагается, что оба файла CSV находятся в том же каталоге, что и сценарий.

#!/bin/sh

ed -s data1.csv <<-'EOF'
    1r data2.csv
    2s/^ID//
    1,2j
    g/^1,[[:digit:]]/ /^1,[[:alpha:]]/t.
    g/^2,[[:digit:]]/ /^2,[[:alpha:]]/t.
    2,3d
    g/^[[:digit:]]/+1s/^[[:digit:]]//
    g/^[[:digit:]]/;/^,.*/j
    ,p
    Q
EOF
0 голосов
/ 05 августа 2020

Использовать esPro c очень просто. Он импортирует два файла CSV и выполняет левое соединение (функция join@1). Если позже будут другие аналитические задания, использование языка SPL esProc будет более естественным, чем SQL. Код SPL для вас:

data1=file("./data1.csv").import@t()
data2=file("./data2.csv").import@t()
data2.keys(ID)
data3=data1.join@1(ID,data2,NAME,AGE,Location)

Если у вас есть другие вопросы, дайте мне знать.

0 голосов
/ 05 августа 2020

Есть несколько способов go об этом, если у вас есть 2 файла csv, иначе это может оказаться непростым делом. Конечно, эти решения будут включать awk, sort et c.

Однако наиболее эффективным и простым способом будет использование csvkit. Сначала установите csvkit: sudo pip install csvkit (вам нужно будет установить python3 и python3 -pip)

В наборе есть различные инструменты, такие как csvcut, csvlook, который позволяет просматривать и вырезать столбцы, которые вы Но для вашего случая csvjoin - эффективный инструмент.

csvjoin -c 1 file1.csv file2.csv Эта команда объединяет два файла в столбце 1.

Подробнее об этом: https://csvkit.readthedocs.io/en/1.0.5/scripts/csvjoin.html

вот мой ответ на немного другой вопрос, вы можете найти его полезным { ссылка }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...