Thêm cột từ một .csv vào tệp .csv khác


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

đầu ra mong muốn.csv

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

Tôi đã thử sử dụng "tham gia" và "dán" nhưng không có kết quả. Có một lệnh bash để làm điều này? Cột "A" giống nhau trong cả hai .csvtệp.


Vì vậy, bạn đang yêu cầu sao chép cột B vào Tệp 1? Hoặc cột C và D vào file2?
Tim

Dù bằng cách nào cũng sẽ ổn miễn là đầu ra khớp với "wishOutput.csv"
Roboman1723

Tôi đã thêm một câu trả lời mới, theo tôi, dễ hơn tất cả các câu trả lời khác (bao gồm câu trả lời đầu tiên của tôi). Bạn có thể muốn xem xét chấp nhận điều đó để tham khảo trong tương lai dễ dàng tìm thấy thông tin.
don.joey

Câu trả lời:


11

Chỉ với awklệnh:

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

Lấy một dòng từ tệp1 và lưu nó vào biến cục bộ f1, sau đó in dòng được lưu trữ f1và cuối cùng in các trường thứ ba ( $3) và tiếp theo ( $3) từ tệp 1 được phân tách bằng dấu phẩy ,và thay đổi OFS (dấu tách trường đầu ra [dấu cách mặc định]) thành dấu phẩy ( ,).


Lệnh ngắn sẽ như thế này:

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

dán tệp2, sau đó cắt và dán cột thứ ba sang cột tiếp theo ( -f3-) từ tệp1.


Với awkpaste(tùy chọn A)

Lệnh bên dưới cũng sao chép hai cột cuối cùng ( C,D) từ tệp1 ở cuối mỗi dòng trong tệp2:

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

Lệnh trên dán nội dung file2 sau đó in dấu phân cách dấu phẩy ( -d',') sau đó dán hai trường cuối cùng ( NFlà chỉ mục của trường cuối cùng và $NFlà chuỗi có chỉ mục của nó NF. Vì vậy, $(NF-1)trường thứ hai trước trường cuối cùng) từ tệp1 khi các chỉ mục đó xác định lại hoặc chia nhỏ với khán giả dấu phẩy ( -F',').

Với awkpaste(tùy chọn B)

Lệnh này cũng giống như trên ( $3$4trỏ đến trường thứ ba và thứ ba của mỗi dòng từ tệp1):

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

Hoặc một giải pháp khác với cutlệnh:

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

Lệnh cắt trong lệnh trên trước tiên cắt trường đầu tiên ( -f1được lập chỉ mục bằng dấu phẩy dấu phẩy ( -d.)) từ tệp1 ( cut -d, -f1 file1), sau đó cắt và dán trường thứ hai của tệp2 ( cut -d, -f2 file2) và cuối cùng cắt và dán cột thứ ba ( -f3) vào nexts ( -) từ file1 ( cut -d, -f3- file1) một lần nữa.

Lệnh này cũng trả về kết quả tương tự:

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

dán trường thứ hai từ tệp1 ( awk -F',' '{print $1}' file1) sau đó in dấu phẩy ( -d,), sau đó dán cột thứ hai từ tệp2 ( awk -F',' '{print $2}' file2), cuối cùng dán lại cột thứ hai và cột cuối cùng của tệp1 ( awk -F',' '{print $3","$4}' file1).


@kasi bạn có thể làm điều này thông qua awk chính nó. Xem stackoverflow.com/a/14984673/3297613
Avinash Raj

9

Đây là một vẻ đẹp (tôi nghĩ):

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

Chia nhỏ theo các bước:

Bước 1. Cài đặt csvkit:

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

Bước 2. Sử dụng lệnh nối với dấu phẩy là dấu phân cách

join -t,

Bước 3. Cho nó ăn các cột thực tế bạn muốn. Lưu ý cách bạn cung cấp cho cột đầu tiên hai lần, bởi vì đó là lần tham gia thực sự được thực hiện trên (hành vi mặc định của join).

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

hoặc viết tắt:

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

Bạn có thể chuyển hướng đầu ra tiêu chuẩn đó đến một tệp (mong muốn) nếu muốn.

Ưu điểm

Phương pháp này có một số lợi thế so với những phương pháp khác được đề xuất.

Đầu tiên và quan trọng nhất: nó thực hiện một sự tham gia thực sự. Điều đó có nghĩa là nó cũng có thể được sử dụng cho dữ liệu phức tạp hơn. Chẳng hạn, rất dễ dàng để tham gia vào một lĩnh vực khác. Nó không chỉ đơn giản là nhìn vào vị trí của trường, mà nó thực sự đưa cột vào xem xét. Nó thực sự hoạt động với định dạng của dữ liệu (csv) và không coi nó như văn bản.

Thứ hai, nó sử dụng bộ công cụ csv rất mạnh mẽ cũng cho phép bạn a) hiển thị số liệu thống kê với một lệnh ( csvstats), b) kiểm tra xem dữ liệu có sạch ( csvclean) không, nhưng cũng để chuyển đổi thành json, thành sql hoặc thậm chí tải nó vào con trăn! Bộ công cụ này được sử dụng nhiều trong khoa học dữ liệu để chuẩn bị dữ liệu.


Nếu bạn đang cài đặt trên Ubuntu, bạn có thể cần cài đặt các tiêu đề phát triển Python trước khi cài đặt csvkit: sudo apt-get install python-dev python-pip python-setuptools build-essential- link
karel

Câu trả lời tuyệt vời là, tôi đang làm việc trên một máy chủ của công ty nên việc cài đặt công cụ mất khoảng một tuần làm việc trên giấy. Hoạt động trên máy của tôi mặc dù!
Roboman1723

+1 để hiển thị cho tôi một công cụ khác cho dữ liệu CSV. Câu hỏi riêng biệt, nhưng bạn có biết một người viết báo cáo độc lập cho các tệp dữ liệu CSV không?
Joe

@Joe bạn có thể nói cụ thể hơn về ý của bạn khi bạn nói về một "người viết báo cáo" không? Tôi không chắc tôi hiểu ý của bạn.
don.joey

Tôi đã đăng một câu hỏi riêng tại unix.stackexchange.com/questions/170199/ triệt
Joe

7

Đây là một cái đẹp khác. Tôi nghĩ rằng đó là cách dễ nhất trong tất cả các đề xuất, cho đến nay.

csvtool pastecol 2 2 file1.csv file2.csv

Nếu bạn chưa cài đặt csvtool trong quá khứ, bạn phải làm sudo apt-get install csvtool.

Từ các tài liệu:

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

Thay thế nội dung của các cột được tham chiếu trong tệp input.csv bằng một trong các cột tương ứng được chỉ định trong update.csv.

Thí dụ:

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

Lưu ý trong trường hợp của chúng tôi, chúng tôi sẽ thay thế các cột thứ hai của các tệp.

Ví dụ

file1.csv

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

file2.csv

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

Kết hợp hai tệp:

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

Những gì bạn chủ yếu làm là dán cột hai của file2.csvcột 2 vào file1.csv.

Lưu ý rằng điều này cũng hoạt động trên cùng một tài liệu. Nếu bạn muốn trao đổi hai cột, bạn có thể làm như vậy bằng cách sử dụng cùng một tệp như input.csv và update.vsc.

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

Không nghi ngờ gì thanh lịch nhất.
Jacob Vlijm

2

Để di chuyển một số cột được chọn từ tệp này sang tệp khác:

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

từ hai tệp:

tập tin_1

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

tập tin_2

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

Khi bạn đặt cols = 1:

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

Nhưng khi bạn đặt 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

Cách sử dụng

Sao chép nó vào một tập tin rỗng, thiết lập đường dẫn đến file1, file2và số cột để di chuyển, tiết kiệm nó như move.pyvà chạy nó bằng cách:

python3 /path/to/move.py

Cũng có thể thêm một hoặc nhiều cột từ giữa các colums của tệp nguồn theo cách này.


Rất thích nhìn thấy bạn sử dụng import csvmặc dù.
don.joey

@ don.joey Cảm ơn lời đề nghị, chắc chắn sẽ xem xét nó.
Jacob Vlijm

0

Một phương pháp khác trong python thông qua mô-đun 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))

Để chạy đoạn script trên,

python3 script.py file1 file2

Đầu ra:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.