eşleşen alanlara dayalı toplam sütun çifti


11

Aşağıdaki biçimde büyük bir dosya var:

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

Sütun 2'deki değerler eşleşirse, her iki satırın sütun 3 ve 4'teki değerleri toplamak istiyorum , aksi takdirde sadece benzersiz satırdaki değerlerin toplamı.

Yani umduğum çıktı şu şekilde olurdu:

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

Ben göre dosyaları sıralamak mümkün duyuyorum sütunda 2 ile awkveya sortve son sütunları özetlemek awkama sadece bireysel hatları için değil iki satır için, sütun 2 maç.


1
1. sütun ne olacak?
glenn jackman

@glennjackman: Sütun 1 her dosyada aynı değere sahiptir. Dosya için bir tanımlayıcı görevi görür (bunlardan 45 tane var) ve bazı aşağı akış işlemleri için kullanılacaktır. Sorum için göz ardı edilebilir (veya silinebilir) ve daha sonra tekrar eklenebilir.
TomPio

ya $1 $2da anahtar olarak yapın.
glenn jackman

Yanıtlar:


12

Bunu Perl'de yapardım:

$ 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

Veya awk:

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

Çıktının ikinci sütuna göre sıralanmasını istiyorsanız, aşağıdakileri yapabilirsiniz sort:

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

Her iki çözümün de 1. sütunu içerdiğini unutmayın. Fikir, ilk ve ikinci sütunları bir karma (perl cinsinden) veya ilişkilendirilebilir bir dizinin (awk cinsinden) anahtarları olarak kullanmaktır. Her çözümün anahtarı, column1 column2iki satırın aynı sütun iki, ancak farklı bir sütun olması durumunda, ayrı ayrı gruplandırılacaktır:

$ 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

Belki bu yardımcı olabilir, ancak sütun 1 her zaman 2'dir ve sonuçlar buna bağlıdır mı?

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

veya sıralama hakkında yorumlarda glenn jackman tarafından belirtildiği gibi :

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'niz varsa, PROCINFO["sorted_in"] = "@ind_num_asc"yerine boru kullanmak yerine kullanın sort. ref gnu.org/software/gawk/manual/html_node/…
glenn jackman

@taliezin: Teşekkürler taliezin ve terdon. Her iki yaklaşım da bir cazibe gibi çalıştı. Yardımın için sağol.
TomPio

1
@taliezin: Her ikisinin de benim için çalıştığını söylediğim gibi, terdon cevaplarını "doğru" olarak işaretledim. Sanırım istediğin buydu. Tekrar teşekkürler.
TomPio

1
Toplam benzersiz anahtarları istediğiniz soruyu anlarsam, bir sayaç ekleyip yazdırabiliriz: awk '{map [$ 2] + = 3 $ + 4 $; } END {for (haritadaki i) {print "2", i, harita [i] | "sort -t'n '"; pulse ++; } "benzersiz toplam:"
cnt

1
Neredeyse aynı: awk '{map [2 $] + = 3 $ + 4 $; oc [$ 2] ++; } END {for (haritadaki i) {print "2", i, harita [i], oc [i] | "sort -t'n '"; }} ', şimdi olaylarla birlikte başka bir sütun göreceksiniz.
taliezin

4

Verileri önceden sıralayabilir ve awk'ın ayrıntıları işlemesine izin verebilirsiniz:

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

Akümülatörü sıfırlamak isteyebilirsiniz:

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

Çıktı:

1019 15
1021 19
1022 28
1030 34

İlk sütunu gerçekten saklamak istiyorsanız, böyle bir şey yapın:

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

Çıktı:

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

açıklama

pDeğişken tutan $2önceki satırın değeri, ya da $1FS$2yukarıdaki ikinci durumda. Bu , önceki satırın geçerli satırdaki ( ) ile aynı olmadığı {print p,s}zaman tetikleneceği anlamına gelir .$2p!=$2


İlk sütun farklı değerlere sahip olsa bile sort -k2, ikinci sütuna göre sıralamak için kullanabileceğinizi unutmayın
gaoithe

2

İsviçre çakısı kullanma mlr:

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

Çıktı:

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

Notlar:

  • --nidxmlrsayısal alan adlarını kullanmayı söyler .

  • put '$5=$3+$4'yeni bir 5. alan oluşturur, 3. ve 4. alanların toplamı .

  • stats1Fonksiyonu (veya " fiil ") daha küçük bir İsviçre Çakısı
    büyük İsviçre çakısı içinde mlrgibi çeşitli akümülatör fonksiyonlarıyla, sum, count, mean, vs.

    stats1 -g 1,2Gruplar sütun veri 1 ve 2 , ve -f 5 -a sumdaha sonra bu grupların alanı ekler 5 . stats1 yalnızca adlandırılmış alanları yazdırır.

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.