Bir .csv dosyasından başka bir .csv dosyasına sütun ekleme


12

file1.csv

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

file2.csv

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

istenen Output.csv

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

Ben boşuna "katılmak" ve "yapıştır" kullanarak denedim. Bunu yapmak için bir bash komutu var mı? "A" sütunu her iki .csvdosyada da aynıdır .


Yani B sütununu Dosya 1'e kopyalamak mı istiyorsunuz? Veya C ve D sütunlarını dosya2'ye?
Tim

Her iki durumda da çıktı "arzu edilenOutput.csv" ile eşleştiği sürece iyi olur
Roboman1723

Sanırım diğer tüm cevaplardan daha kolay olan yeni bir cevap ekledim (ilk cevabım dahil). İleride başvurmak üzere bilgilerin kolayca bulunabilmesi için bunu kabul etmeyi düşünebilirsiniz.
don.joey

Yanıtlar:


11

Sadece awkkomut ile:

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

Dosya1'den bir satır alın ve yerel değişkene depolayın f1, ardından depolanan satırı yazdırın f1ve son olarak virgülle ayrılmış dosya1'den üçüncü ( $3) ve ileri ( $3) alanlarını yazdırın ,ve OFS (çıktı alanı ayırıcısını [boşluk varsayılan]) - virgül ( ,).


Kısa komut şöyle olacaktır:

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

dosya2'yi yapıştırın, ardından üçüncü sütunu -f3-dosya1'deki next ( ) öğesine yapıştırın .


İle awkve paste(A seçeneği)

Aşağıdaki komut ayrıca C,Ddosya2'deki dosya1'deki son iki sütunu ( ) kopyalar :

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

Komutun üstüne file2 içeriğini yapıştırın , ardından bir virgül ayırıcı ( -d',') yazdırın ve sonra son iki alanı yapıştırın (son alanın NFdizini ve dizininin $NFbulunduğu dizedir NF. Yani $(NF-1)bu alan yeniden tanımlandığında dosya1'den son alanın önündeki ikinci alan) veya virgül izleyici ( -F',') ile böler .

İle awkve paste(B seçeneği)

Bu komut ayrıca yukarıdakiyle aynıdır ( $3ve $4dosya1'deki her satırın üçüncü ve dördüncü alanını işaret eder):

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

Veya şu cutkomutu içeren başka bir çözüm :

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

kesim Yukarıdaki komutu komut (birinci alan kesme -f1virgül sınırlayıcı (dizinlenmiş -d.Dosya1 () 'den) cut -d, -f1 file1), daha sonra kesilmiş ve dosya2'nin (ikinci alan yapıştırma cut -d, -f2 file2) ve son olarak kesilmiş ve (üçüncü sütun yapıştırmak -f3(nExts için) -) dosya1 ( cut -d, -f3- file1) 'den tekrar.

Bu komut aynı sonucu döndürür:

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

ikinci alanı dosya1'den ( awk -F',' '{print $1}' file1) -d,yapıştırın, ardından bir virgül ( ) yazdırın , sonra ikinci sütunu dosya2'den ( awk -F',' '{print $2}' file2) yapıştırın, son olarak dosya1'in ( ) ikinci ve son sütununu awk -F',' '{print $3","$4}' file1tekrar yapıştırın .


@kasi bunu awk'nin kendisinden yapabilirsin. Bkz. Stackoverflow.com/a/14984673/3297613
Avinash Raj

9

İşte bir güzellik (sanırım):

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

Adımlarla ayrıldı:

1. Adım. Csvkit'i yükleyin:

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

Adım 2. Ayırıcı olarak join komutunu virgülle kullanın

join -t,

Adım 3. İstediğiniz gerçek sütunları besleyin. İlk sütunu iki kez nasıl beslediğinize dikkat edin, çünkü birleştirmenin gerçekte gerçekleştirildiği budur (varsayılan davranışı join).

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

veya kısaca:

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

İsterseniz, standart çıktıyı bir dosyaya (desiredOutput) yönlendirebilirsiniz.

Avantajları

Bu yöntemin önerilen diğerlerine göre birçok avantajı vardır.

Her şeyden önce: gerçek bir birleştirme yapar. Bu, daha karmaşık veriler için de kullanılabileceği anlamına gelir. Örneğin, başka bir alanda birleştirme yapmak çok kolaydır. Sadece alanın pozisyonuna bakmaz, aynı zamanda sütunu gerçekten dikkate alır. Aslında veri biçimi (csv) ile çalışır ve metin gibi davranmaz.

İkincisi, aynı zamanda a) bir komutla istatistikleri görüntülemenizi ( csvstats), b) verilerin temiz olup olmadığını kontrol etmenizi ( csvclean), aynı zamanda json'a, sql'e dönüştürmenizi veya hatta yüklemenizi sağlar. piton! Bu araç seti veri hazırlamada veri biliminde yoğun olarak kullanılmaktadır.


Eğer Ubuntu üzerinde kuruyorsanız csvkit yüklemeden önce Python geliştirme başlıkları yüklemeniz gerekebilir: sudo apt-get install python-dev python-pip python-setuptools build-essential- bağlantıyı
karel

Müthiş cevap da, bir şirket sunucusunda çalışıyorum, bu yüzden bir şey yüklemek yaklaşık bir hafta kağıt işi sürüyor. Gerçi benim makinemde çalışıyor!
Roboman1723

Bana CSV verileri için başka bir araç göstermek için +1. Ayrı bir soru, ancak CSV veri dosyaları için bağımsız bir rapor yazarı biliyor musunuz?
Joe

@Joe, bir 'rapor yazarı' hakkında konuşurken ne demek istediğiniz hakkında daha spesifik olabilir misiniz? Ne demek istediğini anladığımdan emin değilim.
don.joey


7

İşte başka bir güzel. Bence şimdiye kadar tüm önerilerin en kolayı bu.

csvtool pastecol 2 2 file1.csv file2.csv

Daha önce csvtool'u henüz yüklemediyseniz, kurmanız gerekir sudo apt-get install csvtool.

Dokümanlardan:

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

İnput.csv dosyasında başvurulan sütunların içeriğini, update.csv dosyasında belirtilen ilgili sütundan biriyle değiştirin.

Misal:

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

Bizim durumumuzda dosyaların ikinci sütunlarını nasıl değiştirdiğimizi unutmayın.

Örnekler

file1.csv

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

file2.csv

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

İki dosyayı birleştirmek:

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

Temelde yaptığınız şey, file2.csvikinci sütunu 2 sütunu olarak yapıştırmaktır file1.csv.

Bunun aynı belge üzerinde de çalıştığını unutmayın. İki sütunu takas etmek istiyorsanız, input.csv ve update.vsc ile aynı dosyayı kullanarak bunu yapabilirsiniz.

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

Şüphesiz en zarif.
Jacob Vlijm

2

Seçilen sayıda sütunu bir dosyadan diğerine taşımak için:

#!/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:]))

iki dosyadan:

file_1

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

file_2

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

Ayarladığınızda cols = 1:

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

Ama ayarladığınızda 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

Nasıl kullanılır

Boş bir dosyaya kopyalayın, yolunu ayarlamak file1, file2ve sütun sayısı olarak kaydedin, hareket etmek move.pyve bunu çalıştırın:

python3 /path/to/move.py

Kaynak dosya sütunlarının ortasından bir veya daha fazla sütun bu şekilde eklenebilir.


Eğer import csvolsa kullanmak görmek isterdim .
don.joey

@ don.joey Öneri için teşekkürler, kesinlikle içine bakacağız.
Jacob Vlijm

0

Csv modülü ile python'da başka bir yöntem.

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))

Yukarıdaki komut dosyasını çalıştırmak için,

python3 script.py file1 file2

Çıktı:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.