UNIX'te GROUP BY benzeri bir komut gerçekleştirin


0

Aşağıdaki gibi bir metin dosyası yaşıyorum:

1 2 3 4 5 6 7 8 9 ... n    <-- column numbering
1 0 0 1 0 0 0 1 0 ... 0
0 1 0 0 0 0 0 0 0 ... 1
1 0 0 0 0 0 0 1 1 ... 0
0 1 1 1 0 1 0 0 0 ... 0
0 1 0 0 1 0 1 0 1 ... 1

Aslında ikili değerlerin olduğu çok seyrek bir matristir. Her satırda birden fazla 1 olmalı ve her sütunda en az bir 1 olmalıdır.

Yapmak istediğim, hangi sütunların 2 1'den daha az diyelim olduğunu bulmak. Mesela yukarıdaki matrisimde 3, 5, 6 ve 7. sütunlardan kurtulmak istiyorum çünkü sadece bir tane var.

Bunu yapmak için bir UNIX komutu var mı? Muhtemelen bir Grup by-like (SQL) komutuna ihtiyacım var ve ardından hangi sütunların belirli bir sayıdan daha az olduğunu takip ettim, ama nasıl yapabileceğimi anlamıyorum.


Hayır! Eğer zap olsaydı satırları <2 1'leri vardı, o zaman hiçbir sorun olurdu. Orijinal soru biraz programlama gerektirecektir.
johntellsall

Yanıtlar:


1

awkAşağıdaki betiği kullanarak matrisi geçmek ve 1 ve 0 sayılarını saymak için kullanabilirsiniz :

count.awk :

NR != 1 {
  for (i=1; i<=NF; ++i)
    count[i] += $i;
}

END {
  ORS = ",";
  for (i=1; i<=length(count); ++i)
    if (count[i] >= min)
       print i
}

Bu betiği kullanarak yürütürseniz

awk -v min=2 -f count.awk matrix.txt

iki ya da daha fazla 1'e sahip bir sütun satırı alacaksınız, bu durumda "1,2,4,8,9" (not: istediğiniz min=Xherhangi bir minimum eşiğe değiştirebilirsiniz ).

Şimdi cutyalnızca istediğimiz sütunları yazdırmak için kullanın :

cols=$(awk -v min=2 -f count.awk matrix.txt); cut -d' ' -f${cols:0:-1} matrix.txt

Bu, awkçıktıyı bir değişkende saklar (bunun nedeni , sonunda awkekstra olan bir sütun listesi döndürür. Sütunları ,ilettiğimde virgül "keser" cut).

Sınırlayıcıyı cut"boşluk" ( -d' ') olarak ve çıkış sütunlarını virgülle ayrılmış listeye awk, son virgül dilimlenmiş ( -f${cols:0:-1}) olacak şekilde ayarlayın.

Çıktı:

1 2 4 8 9 n
1 0 1 1 0 0
0 1 0 0 0 1
1 0 0 1 1 0
0 1 1 0 0 0
0 1 0 0 1 1

1'den az sütunları min(örneğin, sütun 3, 5, 6, 7) çıkarmak ifisterseniz awk, okumak için yukarıdaki komut dosyasındaki ifadenin durumunu tersine çevirin if (count[i] < min).

Çıktı:

3 5 6 7
0 0 0 0
0 0 0 0
0 0 0 0
1 0 1 0
0 1 0 1

Bunun için teşekkürler. Aslında kod muhtemelen bazı problemler yaşıyor. NR! = 1 bölüm ne için? EDIT: NR> 0 ile çalışır.
ddmichael

@ ddmichael NR != 1, başlık satırını sütun numaralandırma ile atlamak için kullanılır. "Kayıt numarası (NR) 1 değilse, aşağıdaki işlemleri yapın" diyor. Benim sistemde NR > 1de çalışır, ancak DEĞİL NR > 0 . Bunun işe yarayacağına şaşırdım - belki awksıfırdan başlıyorsunuz?
savanto,

Ah, evet haklısın.
ddmichael
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.