คู่ผลรวมของคอลัมน์ตามเขตข้อมูลที่ตรงกัน


11

ฉันมีไฟล์ขนาดใหญ่ในรูปแบบต่อไปนี้:

2 1019 0 12 
2 1019 3 0 
2 1021 0 2 
2 1021 2 0 
2 1022 4 5
2 1030 0 1 
2 1030 5 0 
2 1031 4 4

หากค่าในคอลัมน์ 2ตรงกันฉันต้องการรวมผลรวมในคอลัมน์ 3และ4ของทั้งสองบรรทัดหรือจะรวมเพียงผลรวมของค่าในบรรทัดที่ไม่ซ้ำกัน

ดังนั้นผลลัพธ์ที่ฉันหวังไว้จะเป็นดังนี้:

2 1019 15 
2 1021 4 
2 1022 9 
2 1030 6 
2 1031 8

ฉันสามารถเรียงลำดับไฟล์ตามคอลัมน์ 2ด้วยawkหรือsortและรวมคอลัมน์สุดท้ายด้วยawkแต่เฉพาะสำหรับแต่ละบรรทัดไม่ใช่สำหรับสองบรรทัดที่คอลัมน์ 2ตรงกัน


1
แล้วคอลัมน์ 1 ล่ะ
เกล็นแจ็คแมน

@glennjackman: คอลัมน์ 1 มีค่าเท่ากันตลอดทั้งไฟล์ มันทำหน้าที่เป็นตัวระบุสำหรับไฟล์ (ฉันมี 45 ของเหล่านั้น) และจะใช้สำหรับกระบวนการดาวน์สตรีมบางอย่าง สำหรับคำถามของฉันมันอาจถูกละเว้น (หรือลบ) และเพิ่มในภายหลังอีกครั้ง
TomPio

หรือทำให้$1 $2เป็นกุญแจสำคัญ
เกล็นแจ็คแมน

คำตอบ:


12

ฉันจะทำเช่นนี้ใน Perl:

$ perl -lane '$k{"$F[0] $F[1]"}+=$F[2]+$F[3]; 
              END{print "$_ $k{$_}" for keys(%k) }' file 
2 1019 15
2 1021 4
2 1030 6
2 1031 8
2 1022 9

หรือ awk:

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file 

หากคุณต้องการเรียงลำดับผลลัพธ์ตามคอลัมน์ที่สองคุณสามารถไปที่sort:

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file | sort -k2

โปรดทราบว่าโซลูชันทั้งสองนี้มีคอลัมน์ที่ 1 เช่นกัน แนวคิดคือการใช้คอลัมน์แรกและคอลัมน์ที่สองเป็นกุญแจสำหรับแฮช (เป็นภาษา perl) หรืออาเรย์แบบเชื่อมโยง (เป็น awk) คีย์ในแต่ละโซลูชันคือcolumn1 column2ดังนั้นหากสองบรรทัดมีคอลัมน์เดียวกันสอง แต่เป็นคอลัมน์ที่แตกต่างกันพวกเขาจะถูกจัดกลุ่มแยกกัน:

$ cat file
2 1019 2 3
2 1019 4 1
3 1019 2 2

$ awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
3 1019 4
2 1019 10

7

อาจช่วยได้ แต่เป็นคอลัมน์ 1 เสมอ 2 และผลลัพธ์ขึ้นอยู่กับมันหรือไม่

awk '{ map[$2] += $3 + $4; } END { for (i in map) { print "2", i, map[i] | "sort -t't'" } }' file

หรือตามที่กล่าวถึงโดยเกล็นแจ็คแมนในความคิดเห็นเกี่ยวกับการเรียงลำดับ:

gawk '{ map[$2] += $3 + $4; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (i in map) { print 2, i, map[i] } }' file

2
ถ้าคุณมี GNU awk ใช้แทนท่อไปPROCINFO["sorted_in"] = "@ind_num_asc" sortref gnu.org/software/gawk/manual/html_node/…
glenn jackman

@taliezin: ขอบคุณ taliezin และ terdon วิธีการทั้งสองทำงานเหมือนมีเสน่ห์ ผมขอขอบคุณความช่วยเหลือของคุณ.
TomPio

1
@taliezin: ตามที่ฉันบอกว่าทั้งสองทำงานให้ฉันฉันทำเครื่องหมายคำตอบ terdon ว่า "ถูกต้อง" ฉันเดาว่านั่นคือสิ่งที่คุณตั้งใจไว้ ขอบคุณอีกครั้ง.
TomPio

1
หากฉันเข้าใจคำถามที่คุณต้องการคีย์ที่ไม่ซ้ำกันทั้งหมดเราสามารถเพิ่มตัวนับและพิมพ์: awk '{map [$ 2] + = $ 3 + $ 4; } END {สำหรับ (i ในแผนที่) {พิมพ์ "2", i, แผนที่ [i] | "sort -t'n '"; CNT ++; } พิมพ์ "total unique:" ไฟล์ cnt} '
taliezin

1
เกือบเหมือนกัน: awk '{map [$ 2] + = $ 3 + $ 4; oc [$ 2] ++; } END {สำหรับ (i ในแผนที่) {พิมพ์ "2", i, แผนที่ [i], oc [i] | "sort -t'n '"; }} 'ตอนนี้คุณจะเห็นคอลัมน์อื่นที่มีเหตุการณ์เกิดขึ้น
taliezin

4

คุณสามารถจัดเรียงข้อมูลล่วงหน้าและให้ awk จัดการรายละเอียดได้:

sort -n infile | awk 'NR>1 && p!=$2 {print p,s} {s+=$3+$4} {p=$2}'

คุณอาจต้องการรีเซ็ตตัวสะสม:

sort -n infile | awk 'NR>1 && p!=$2 {print p,s;s=0} {s+=$3+$4} {p=$2}'

เอาท์พุท:

1019 15
1021 19
1022 28
1030 34

หากคุณต้องการเก็บคอลัมน์แรกไว้ให้ทำดังนี้:

sort -n infile | awk 'NR>1 && p!=$1FS$2 {print p,s} {s+=$3+$4} {p=$1FS$2}'

เอาท์พุท:

2 1019 15
2 1021 19
2 1022 28
2 1030 34

คำอธิบาย

pตัวแปรถือ$2มูลค่าของบรรทัดก่อนหน้าหรือ$1FS$2ในกรณีที่สองดังกล่าวข้างต้น ซึ่งหมายความว่า{print p,s}มีการทริกเกอร์เมื่อ$2ของบรรทัดก่อนหน้าไม่เหมือนกันในบรรทัดปัจจุบัน ( p!=$2)


โปรดทราบว่าแม้ว่าคอลัมน์แรกจะมีค่าแตกต่างกันคุณสามารถใช้sort -k2จัดเรียงตามคอลัมน์ที่สอง
gaoithe

2

การใช้มีดกองทัพสวิสใช้mlr:

mlr --nidx   put '$5=$3+$4'   then   stats1 -g 1,2 -f 5 -a sum   infile

เอาท์พุท:

2   1019    15
2   1021    4
2   1022    9
2   1030    6
2   1031    8

หมายเหตุ:

  • --nidxบอกmlrให้ใช้ชื่อฟิลด์ตัวเลข

  • put '$5=$3+$4'ทำให้ใหม่5สนามรวมของฟิลด์3และ4

  • stats1ฟังก์ชั่น (หรือ " คำกริยา ") เป็นมีดทหารสวิสที่มีขนาดเล็ก
    ภายในมากขึ้นมีดทหารของสวิสmlrที่มีฟังก์ชั่นสะสมหลายเช่นsum, count, mean, ฯลฯ

    stats1 -g 1,2กลุ่มข้อมูลตามคอลัมน์ที่1และ2และ-f 5 -a sumหลังจากนั้นก็เพิ่มขึ้นฟิลด์กลุ่มเหล่านั้น5 stats1 พิมพ์ฟิลด์ที่มีชื่อเท่านั้น

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