Dodaj kolumnę z jednego pliku .csv do innego pliku .csv


12

plik1.csv

A,,C,D
A,,C,D
A,,C,D
A,,C,D

plik2.csv

A,B
A,B
A,B
A,B

pożądany Output.csv

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D

Próbowałem użyć „dołącz” i „wklej” bezskutecznie. Czy istnieje do tego polecenie bash? Kolumna „A” jest taka sama w obu .csvplikach.


Pytasz więc o skopiowanie kolumny B do pliku 1? Lub kolumny C i D do pliku 2?
— Tim

Tak czy inaczej, wszystko będzie dobrze, o ile dane wyjściowe będą pasować do „pożądanego wyjścia.csv”
— Roboman1723,

Dodałem nową odpowiedź, która moim zdaniem jest łatwiejsza niż wszystkie inne odpowiedzi (w tym moja pierwsza odpowiedź). Możesz rozważyć zaakceptowanie tego, aby w przyszłości łatwo było znaleźć informacje.
— don.joey

Odpowiedzi:


11

Tylko z awkpoleceniem:

awk -F, '{getline f1 <"file2" ;print f1,$3,$4}' OFS=, file1

Pobierz wiersz z pliku 1 i zapisz go w zmiennej lokalnej f1, a następnie wydrukuj wiersz, który jest zapisany, f1i na końcu wydrukuj pola trzecie ( $3) i czwarte ( ) $3z pliku 1, które są rozdzielone przecinkiem ,, i zmień OFS (separator pól wyjściowych [spacja przez default]) do przecinka ( ,).


Krótkie polecenie wyglądałoby tak:

paste -d, file2 <(cut -d, -f3- file1)
 A, B, C, D  
 A, B, C, D  
 A, B, C, D  
 A, B, C, D  

wklej plik2, a następnie wytnij i wklej trzecią kolumnę do następnej ( -f3-) z pliku1.


Z awki paste(opcja A)

Poniższe polecenie kopiuje również dwie ostatnie kolumny ( C,D) z pliku1 na końcu każdej linii w pliku2:

paste -d',' file2  <(awk -F',' '{print $(NF-1)","$NF}' file1)

Powyższe polecenie wklej zawartość pliku 2, następnie wydrukuj separator przecinka ( -d','), a następnie wklej dwa ostatnie pole ( NFjest indeksem ostatniego pola i $NFciągiem, którego jest indeksem NF. Podobnie $(NF-1)jak drugie pole przed ostatnim polem) z pliku 1, gdy indeks ten redefiniuje lub dzieli za pomocą przecinka ( -F',').

Z awki paste(opcja B)

To polecenie jest również takie samo jak powyżej ( $3i $4wskazuje na trzecie i czwarte pole każdej linii z pliku1):

paste -d',' file2  <(awk -F',' '{print $3","$4}' file1)

Lub inne rozwiązanie z cutpoleceniem:

paste -d, <(cut -d, -f1 file1) <(cut -d, -f2 file2) <(cut -d, -f3- file1)

polecenie cut w powyższym poleceniu najpierw wytnij pierwsze pole ( -f1indeksowane przecinkiem ( -d.)) z file1 ( cut -d, -f1 file1), następnie wytnij i wklej drugie pole file2 ( cut -d, -f2 file2), a na koniec wytnij i wklej trzecią kolumnę ( -f3) do następnej ( -) z pliku1 ( cut -d, -f3- file1) ponownie.

To polecenie zwraca również ten sam wynik:

paste -d, <(awk -F',' '{print $1}' file1) <(awk -F',' '{print $2}' file2) <(awk -F',' '{print $3","$4}' file1)

wklej drugie pole z pliku1 ( awk -F',' '{print $1}' file1), następnie wydrukuj przecinek ( -d,), następnie wklej drugą kolumnę z pliku2 ( awk -F',' '{print $2}' file2), w końcu wklej ponownie drugą i ostatnią kolumnę pliku1 ( awk -F',' '{print $3","$4}' file1).


@ kasi możesz to zrobić przez sam awk. Patrz stackoverflow.com/a/14984673/3297613
— Avinash Raj

9

Oto piękno (tak myślę):

join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)

Podzielone na etapy:

Krok 1. Zainstaluj csvkit:

sudo pip install csvkit
sudo apt-get install python-dev python-pip python-setuptools build-essential

Krok 2. Użyj polecenia łączyć z przecinkiem jako separatorem

join -t,

Krok 3. Podaj rzeczywiste kolumny, które chcesz. Zwróć uwagę, w jaki sposób podajesz go do pierwszej kolumny dwa razy, ponieważ jest to ta, na której faktycznie wykonywane jest łączenie (zachowanie domyślne join).

join -t, <(csvcut --columns 1,3,4 file1.csv) <(csvcut --columns 1,2 file2.csv)

lub w skrócie:

join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)

Możesz przekierować to standardowe wyjście do pliku (pożądanego wyjścia), jeśli chcesz.

Zalety

Ta metoda ma kilka zalet w stosunku do innych proponowanych.

Przede wszystkim: wykonuje prawdziwe połączenie. Oznacza to, że można go również wykorzystać do bardziej złożonych danych. Na przykład bardzo łatwo jest wykonać złączenie w innym polu. Nie tylko patrzy na pozycję pola, ale tak naprawdę bierze pod uwagę kolumnę. W rzeczywistości działa z formatem danych (csv) i nie traktuje tego jak tekstu.

Po drugie, wykorzystuje bardzo potężny zestaw narzędzi csv, który pozwala również na a) wyświetlanie statystyk za pomocą jednego polecenia ( csvstats), b) sprawdzanie, czy dane są czyste ( csvclean), ale także przekształcanie ich w json, sql, a nawet ładowanie do pyton! Ten zestaw narzędzi jest szeroko stosowany w analizie danych do przygotowywania danych.


Jeśli instalujesz na Ubuntu, może być konieczne zainstalowanie nagłówków programistycznych Python przed instalacją csvkit: sudo apt-get install python-dev python-pip python-setuptools build-essential- link
— karel

Świetna odpowiedź, pracuję też na serwerze firmowym, więc instalacja zajmuje około tygodnia papierkowej roboty. Działa na moim komputerze!
— Roboman1723,

+1 za pokazanie mi innego narzędzia do danych CSV. Oddzielne pytanie, ale czy znasz niezależnego autora raportów dla plików danych CSV?
— Joe

@Joe, czy możesz bardziej szczegółowo określić, co masz na myśli, mówiąc o „pisarzu raportów”? Nie jestem pewien, czy rozumiem, co masz na myśli.
— don.joey


7

Oto kolejny piękny. Myślę, że jak dotąd jest to najłatwiejsza ze wszystkich sugestii.

csvtool pastecol 2 2 file1.csv file2.csv

Jeśli nie instalowałeś już csvtool w przeszłości, musisz to zrobić sudo apt-get install csvtool.

Z dokumentów:

pastecol <column-spec1> <column-spec2> input.csv update.csv

Zamień zawartość kolumn, do których odwołuje się plik w pliku input.csv, na jedną z odpowiednich kolumn określonych w pliku update.csv.

Przykład:

  csvtool pastecol 2-3 1- input.csv update.csv.csv > output.csv

Zwróć uwagę, jak w naszym przypadku zastępujemy drugie kolumny plików.

Przykłady

plik1.csv

A,,C,D
A,,C,D
A,,C,D
A,,C,D

plik2.csv

A,B
A,B
A,B
A,B

Łączenie dwóch plików:

csvtool pastecol 2 2 file1.csv file2.csv
A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D

Zasadniczo wklejasz drugą file2.csvkolumnę jako kolumnę 2 do file1.csv.

Pamiętaj, że działa to również w tym samym dokumencie. Jeśli chcesz zamienić dwie kolumny, możesz to zrobić, używając tego samego pliku co input.csv i update.vsc.

csvtool pastecol 2 1 file2.csv file2.csv 
A,A
A,A
A,A 
A,A

Bez wątpienia najbardziej elegancki.
— Jacob Vlijm

2

Aby przenieść wybraną liczbę kolumn z jednego pliku do drugiego:

#!/usr/bin/env python3

cols = 1; file_1 = "/path/to/file_1"; file_2 = "/path/to/file_2"

def readfile(file):
      with open(file) as src:
          return [item.strip().split(",") for item in src.readlines()]

file_1 = readfile(file_1); file_2 = readfile(file_2)

for i in range(len(file_1)):
    print((",").join(file_1[i]+file_2[i][-cols:]))

z dwóch plików:

plik_1

A,B
A,B
A,B
A,B

plik_2

K,L,M
K,L,M
K,L,M
K,L,M

Po ustawieniu cols = 1:

A,B,M
A,B,M
A,B,M
A,B,M

Ale kiedy ustawisz cols = 2:

A,B,L,M
A,B,L,M
A,B,L,M
A,B,L,M

cols = 3:

A,B,K,L,M
A,B,K,L,M
A,B,K,L,M
A,B,K,L,M

Jak używać

Skopiuj go do pustego pliku, należy ustawić ścieżkę file1, file2a liczba kolumn, aby przenieść, zapisać go jako move.pyi uruchomić go przez:

python3 /path/to/move.py

W ten sposób można również dodać jedną lub więcej kolumn ze środka kolumn pliku źródłowego.


Chciałbym zobaczyć, jak używasz import csv.
— don.joey

@ don.joey Dzięki za sugestię, na pewno ją przeanalizuję.
— Jacob Vlijm

0

Inna metoda w pythonie poprzez moduł csv.

script.py

#!/usr/bin/python3
import csv
import sys
file1 = sys.argv[1]
file2 = sys.argv[2]
with open(file2, 'r') as r:
    with open(file1, 'r') as f:
        csv_f = csv.reader(f)
        csv_r = csv.reader(r)
        bar = [linex for linex in csv_r]
        foo = [liney[2:] for liney in csv_f]
        zipped = zip(bar,foo)
        result = [x+y for (x,y) in list(zipped)]
        for i in result:
            print(','.join(i))

Aby uruchomić powyższy skrypt,

python3 script.py file1 file2

Wynik:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.