ทำดัชนีไฟล์ CSV ใหม่อีกครั้ง


11

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

ฉันมีไฟล์ CSV ขนาดใหญ่ (200+ GB) พร้อมแถวที่มีลักษณะดังนี้:

<alphanumerical_identifier>,<number>

ที่<alphanumerical_identifier>ไม่ซ้ำกันในไฟล์ทั้งหมด ฉันต้องการสร้างไฟล์แยกที่แทนที่คอลัมน์แรกด้วยดัชนีเช่น

<index>,<number>

เพื่อให้เราได้รับ:

1, <number>
2, <number>
3, <number>

สามารถawkสร้างดัชนีที่เพิ่มขึ้นโดยไม่โหลดไฟล์เต็มในหน่วยความจำได้ไหม?

เนื่องจากดัชนีเพิ่มขึ้นแบบ monotonically มันอาจจะดีกว่าถ้าจะวางดัชนี วิธีแก้ปัญหาสำหรับสิ่งนั้นจะแตกต่างกันหรือไม่เช่น:

<number>
<number>
<number>

ฉันไม่แน่ใจเกี่ยวกับความเป็นไปได้ของโซลูชันนี้ แต่จะสร้างตัวเลขได้มากเท่าในไฟล์ CSV ในไฟล์แยกต่างหากจากนั้นต่อท้ายคอลัมน์ที่สองของไฟล์ CSV ไปยังไฟล์นั้น
Ramesh

@Ramesh ที่ดีอย่างสมบูรณ์ตราบใดที่ผลลัพธ์ถูกต้อง
Amelio Vazquez-Reina

2
ฉันสงสัยว่าฉันเข้าใจผิดบางอย่าง; มิฉะนั้นawk -F, '{print ++n, $2}'จะทำงาน หรือawk -F, '{print $2}'สำหรับรูปแบบที่สอง
G-Man กล่าวว่า 'Reinstate Monica'

2
@ G-Man นั่นอาจเป็นได้แม้ว่าFNRจะให้บริการเช่นเดียวกับ++n
iruvar

1
ฉันตรวจสอบสามครั้งว่าคุณสามารถกำจัด Uniq Identifier นั้นจริง ๆ ... ทำไมไม่เพิ่มคอลัมน์แรก (ที่ 3) ด้วยดัชนี แต่ยังคงรักษาตัวระบุไว้อยู่? ไม่ใช่ตัวระบุที่ใช้ที่อื่นหรือ
Olivier Dulac

คำตอบ:


13

ไม่ใกล้เทอร์มินัลเพื่อทดสอบ แต่วิธีการเกี่ยวกับnlคำสั่งที่มองข้าม? สิ่งที่ต้องการ:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv


1
PS: ไฟล์200GB CSV หรือไม่ ว้าวและฉันคิดว่าการทำงานกับฐานข้อมูลหมายเลขพอร์ตอเมริกาเหนือในรูปแบบ CSV (ดีวีดีสองสามแผ่น) นั้นใหญ่มาก!
บิชอป

1
มันใช้งานได้แม้ว่าจะมีช่องว่างขนาดใหญ่หลังหมายเลข ฉันจะแทนที่ด้วย:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
แองเกล

@Angel: ขอบคุณอัปเดตคำตอบของฉันเพื่อใช้ตัวเลือกความกว้าง-w 1แทนการใช้ตัวเลขซ้าย
บิชอป

ขอบคุณ @ Bishop - ชื่อไฟล์อินพุตและเอาต์พุตจะไปไหน
Amelio Vazquez-Reina

1
@ user815423426 ใช่cutคำสั่งก่อนสัญลักษณ์ไปป์ ( |) จะให้คุณแค่คอลัมน์ที่สองโดยมีหมายเลขบรรทัดโดยนัย
บิชอป

7

ต่อไปนี้เป็นวิธีการเล็กน้อย แต่ไม่มีวิธีใดที่จะเข้าถึงความเร็วcutและnlวิธีแก้ปัญหาด้านบน:

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
  2. Perl

    perl -pe 's/[^,]+/$./' file.csv > newfile.csv

    หรือ

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (แต่ฉันไม่แนะนำสำหรับไฟล์ 200G มันจะใช้เวลานาน)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv
    

การแก้ปัญหาข้างต้นจะถูกจัดเรียงตามลำดับความเร็ว ฉันทดสอบบนแล็ปท็อปของฉันและไฟล์ 40M และพวกเขาใช้เวลา (เฉลี่ย 10 รัน) 2.2282 (awk), 2.4555 (1st perl), 3.1825s (2nd perl) และ 48.6035s สำหรับเชลล์ วิธีแก้ปัญหาที่ชาญฉลาดcutและnlคุณใช้งานได้นั้นเร็วขึ้นประมาณ 0.6078 วินาที


เยี่ยมมากขอบคุณสำหรับสถิติ! ผลของเปลือกนั้นทำให้ฉันประหลาดใจบ้าง หากคุณแทนที่printfด้วยechoระยะเวลาจะดีขึ้นอย่างมีนัยสำคัญหรือไม่
บิชอป

2
ประมวลผลไฟล์ 40G ในเวลา 2.2282 วินาทีหรือไม่ ฉันจะหาแล็ปท็อปเครื่องนั้นได้จากที่ไหน
John B

2
@JohnB umm ใช่ขอโทษนั่นคือ 40M ไม่ใช่ G :)
terdon

ผมชอบตั้งค่าของวิธีการที่มี$1 แก้ปัญหาคือแน่นอนได้เร็วขึ้นมาก แต่ที่เป็นที่คาดหวังที่มันไม่ได้เปลี่ยนอะไร ผมคิดว่าเร็วที่สุดที่แตกต่างกันอาจจะเป็นสิ่งที่ชอบ awkcut<alphanumerical_identifier>awkmawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv
จอห์น B

@ JohnB ใช่ฉันเดาว่าการใช้OFSแทนที่จะพิมพ์อย่างชัดเจน,จะเร็วขึ้นเล็กน้อยและอาจเพิ่มความแตกต่างอย่างมีนัยสำคัญในไฟล์ขนาดใหญ่
terdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.