เพิ่มคอลัมน์จาก. csv หนึ่งไปยังอีกไฟล์. csv


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

Output.csv ที่ต้องการ

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

ฉันได้ลองใช้ "เข้าร่วม" และ "วาง" เพื่อไม่เป็นประโยชน์ มีคำสั่ง bash ให้ทำเช่นนี้หรือไม่? คอลัมน์ "A" เหมือนกันใน.csvไฟล์ทั้งสอง


ดังนั้นคุณจึงขอให้คัดลอกคอลัมน์ B ไปยัง File 1 หรือคอลัมน์ C และ D ถึง file2?
ทิม

ไม่ว่าจะด้วยวิธีใดก็ตามตราบใดที่ผลลัพธ์ตรงกับ "ที่ต้องการเอาท์พุท. csv"
Roboman1723

ฉันได้เพิ่มคำตอบใหม่ซึ่งฉันคิดว่าง่ายกว่าคำตอบอื่น ๆ ทั้งหมด (คำตอบแรกของฉันรวมอยู่ด้วย) คุณอาจต้องการพิจารณายอมรับว่าเพื่อให้การอ้างอิงในอนาคตพบข้อมูลได้ง่าย
don.joey

คำตอบ:


11

ด้วยawkคำสั่งเท่านั้น:

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

รับบรรทัดจาก file1 และเก็บไว้ในตัวแปรโลคัลf1จากนั้นพิมพ์บรรทัดที่เก็บไว้f1และพิมพ์ฟิลด์ที่สาม ( $3) และถัดไป ( $3) จาก file1 ซึ่งคั่นด้วยเครื่องหมายจุลภาค,โดยสิ้นเชิงและเปลี่ยน OFS (ตัวคั่นฟิลด์เอาท์พุต [ช่องว่างด้วย เริ่มต้น]) ถึงเครื่องหมายจุลภาค ( ,)


คำสั่งสั้น ๆ จะเป็นดังนี้:

paste -d, file2 <(cut -d, -f3- file1)
 เอบีซีดี  
 เอบีซีดี  
 เอบีซีดี  
 เอบีซีดี  

วาง file2 จากนั้นตัดและวางคอลัมน์ที่สามไปยังถัดไป ( -f3-) จาก file1


ด้วยawkและpaste(ตัวเลือก A)

คำสั่งด้านล่างยังคัดลอกสองคอลัมน์สุดท้าย ( C,D) จาก file1 ที่ท้ายบรรทัดแต่ละบรรทัดใน file2:

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

คำสั่งข้างต้นวางเนื้อหา file2 จากนั้นพิมพ์ตัวคั่นจุลภาค ( -d',') แล้ววางสองฟิลด์สุดท้าย ( NFเป็นดัชนีของฟิลด์สุดท้ายและ$NFเป็นสตริงที่ดัชนีของมันคือNFดังนั้น$(NF-1)ฟิลด์ที่สองก่อนฟิลด์สุดท้าย) จาก file1 เมื่อดัชนีเหล่านั้นนิยามใหม่ หรือแยกด้วยเครื่องหมายจุลภาค ( -F',')

ด้วยawkและpaste(ตัวเลือก B)

คำสั่งนี้เหมือนกันกับข้างบน ( $3และ$4ชี้ไปที่ฟิลด์ที่สามและสี่ของแต่ละบรรทัดจาก file1):

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

หรือโซลูชันอื่นที่มีcutคำสั่ง:

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

คำสั่งcutในคำสั่งด้านบนก่อนตัดฟิลด์แรก ( -f1ซึ่งจัดทำดัชนีด้วยตัวคั่นจุลภาค ( -d.)) จาก file1 ( cut -d, -f1 file1) จากนั้นตัดและวางฟิลด์ที่สองของ file2 ( cut -d, -f2 file2) และในที่สุดก็ตัดแล้ววางคอลัมน์ที่สาม ( -f3) ไปยัง nexts ( -) จาก file1 ( cut -d, -f3- file1) อีกครั้ง

คำสั่งนี้จะส่งคืนผลลัพธ์เดียวกัน:

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

วางฟิลด์ที่สองจาก file1 ( awk -F',' '{print $1}' file1) จากนั้นพิมพ์คอมมา ( -d,) จากนั้นวางคอลัมน์ที่สองจาก file2 ( awk -F',' '{print $2}' file2) จากนั้นวางคอลัมน์ที่สองและสุดท้ายของ file1 ( awk -F',' '{print $3","$4}' file1) อีกครั้ง


@kasi คุณสามารถทำได้ผ่าน awk เอง ดูstackoverflow.com/a/14984673/3297613
Avinash Raj

9

นี่คือความงาม (ฉันคิดว่า):

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

แยกย่อยตามขั้นตอน:

ขั้นตอนที่ 1 ติดตั้ง csvkit:

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

ขั้นตอนที่ 2 ใช้คำสั่ง join กับเครื่องหมายจุลภาคเป็นตัวคั่น

join -t,

ขั้นตอน 3. ป้อนคอลัมน์จริงที่คุณต้องการ โปรดทราบวิธีที่คุณป้อนคอลัมน์แรกสองครั้งเพราะนั่นคือการเข้าร่วมที่เกิดขึ้นจริง (พฤติกรรมเริ่มต้นของjoin)

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

หรือในชวเลข:

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

คุณสามารถเปลี่ยนเส้นทางเอาต์พุตมาตรฐานไปยังไฟล์ (ต้องการเอาท์พุท) ถ้าต้องการ

ข้อดี

วิธีนี้มีข้อดีหลายประการมากกว่าวิธีอื่นที่เสนอ

ก่อนอื่น: มันทำการเข้าร่วมจริง นั่นหมายความว่ามันสามารถใช้สำหรับข้อมูลที่ซับซ้อนมากขึ้นเช่นกัน ยกตัวอย่างเช่นการเข้าร่วมในสาขาอื่นเป็นเรื่องง่าย มันไม่เพียงแค่ดูที่ตำแหน่งของสนาม แต่มันจะพิจารณาคอลัมน์ด้วย มันใช้งานได้จริงกับรูปแบบของข้อมูล (csv) และไม่ถือว่าเป็นข้อความ

ประการที่สองมันใช้ชุดเครื่องมือ csv ที่ทรงพลังซึ่งช่วยให้คุณ a) แสดงสถิติด้วยคำสั่งเดียว ( csvstats), b) ตรวจสอบว่าข้อมูลสะอาด ( csvclean) แต่ยังแปลงเป็น json, sql หรือแม้แต่โหลดลงใน หลาม! ชุดเครื่องมือนี้ใช้อย่างมากในศาสตร์ข้อมูลเพื่อการเตรียมข้อมูล


หากคุณกำลังติดตั้งบน Ubuntu คุณอาจต้องติดตั้งส่วนหัว Python สำหรับการพัฒนาก่อนที่จะติดตั้ง csvkit: sudo apt-get install python-dev python-pip python-setuptools build-essential- link
karel

คำตอบที่ยอดเยี่ยมเช่นกันฉันทำงานบนเซิร์ฟเวอร์ของ บริษัท ดังนั้นการติดตั้งสิ่งต่าง ๆ ใช้เวลาประมาณหนึ่งสัปดาห์ในการทำงานของกระดาษ ใช้งานได้กับเครื่องของฉัน!
Roboman1723

+1 สำหรับแสดงเครื่องมืออื่นสำหรับข้อมูล CSV แยกคำถาม แต่คุณรู้จักตัวเขียนรายงานแบบสแตนด์อโลนสำหรับไฟล์ข้อมูล CSV หรือไม่
โจ

@ Joe คุณจะเจาะจงมากขึ้นเกี่ยวกับสิ่งที่คุณหมายถึงเมื่อคุณพูดถึง 'ผู้เขียนรายงาน' หรือไม่? ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณหมายถึง
don.joey

ฉันโพสต์คำถามแยกต่างหากที่unix.stackexchange.com/questions/170199/…
โจ

7

นี่คืออีกหนึ่งที่สวยงาม ฉันคิดว่ามันเป็นวิธีที่ง่ายที่สุดสำหรับคำแนะนำทั้งหมดจนถึงตอนนี้

csvtool pastecol 2 2 file1.csv file2.csv

หากคุณไม่ได้ติดตั้ง csvtool sudo apt-get install csvtoolแล้วในอดีตที่คุณต้อง

จากเอกสาร:

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

แทนที่เนื้อหาของคอลัมน์ที่อ้างอิงโดยในไฟล์ input.csv ด้วยหนึ่งในคอลัมน์ที่เกี่ยวข้องที่ระบุโดยใน update.csv

ตัวอย่าง:

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

สังเกตว่าในกรณีของเราเรากำลังแทนที่คอลัมน์ที่สองของไฟล์

ตัวอย่าง

file1.csv

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

file2.csv

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

การรวมสองไฟล์:

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

สิ่งที่คุณทำคือหลักวางคอลัมน์สองfile2.csvคอลัมน์ file1.csv2

โปรดทราบว่าสิ่งนี้ใช้ได้กับเอกสารเดียวกัน หากคุณต้องการสลับสองคอลัมน์คุณสามารถทำได้โดยใช้ไฟล์เดียวกันกับ input.csv และ update.vsc

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

ไม่ต้องสงสัยเลยว่าสง่างามที่สุด
Jacob Vlijm

2

วิธีย้ายจำนวนคอลัมน์ที่เลือกจากไฟล์หนึ่งไปยังอีกไฟล์หนึ่ง:

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

จากสองไฟล์:

file_1

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

file_2

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

เมื่อคุณตั้งค่าcols = 1:

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

แต่เมื่อคุณตั้งค่า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

วิธีใช้

คัดลอกลงในไฟล์ที่ว่างเปล่าตั้งเส้นทางไปfile1, file2และจำนวนคอลัมน์ที่จะย้ายบันทึกเป็นmove.pyและเรียกใช้โดย:

python3 /path/to/move.py

นอกจากนี้ยังเป็นไปได้ที่จะเพิ่มคอลัมน์หนึ่งคอลัมน์ขึ้นไปจากส่วนกลางของโคลอนของไฟล์ต้นฉบับด้วยวิธีนี้


อยากที่จะเห็นคุณใช้import csvแม้ว่า
don.joey

@ don.joey ขอบคุณสำหรับคำแนะนำจะดูเป็นอย่างแน่นอน
Jacob Vlijm

0

วิธีอื่นในหลามผ่านโมดูล 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))

เพื่อเรียกใช้สคริปต์ข้างต้น

python3 script.py file1 file2

เอาท์พุท:

A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.