在 UNIX 中执行类似 GROUP BY 的命令

在 UNIX 中执行类似 GROUP BY 的命令

我有一个如下的文本文件:

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

实际上是一个非常稀疏的矩阵,其中二进制值。每行应该有多个 1,每列至少有一个 1。

我想要做的是找出哪些列中的 1 少于 2 个。例如,在上面的矩阵中,我想删除第 3、5、6 和 7 列,因为它们只有一个 1。

有没有 UNIX 命令可以做到这一点?可能我需要一个类似 Group by 的 (SQL) 命令,然后跟踪哪些列小于某个数字,但我不知道该怎么做。

答案1

您可以使用awk以下脚本来遍历矩阵并计算 1 和 0 的数量:

计数工具

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
}

如果你使用以下方式执行此脚本

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

您将得到一行包含两个或更多个 1 的列,在本例中为“1,2,4,8,9”(注意:您可以将其更改min=X为您想要的任何最小阈值)。

现在,cut仅打印出我们想要的列:

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

这会将awk输出存储在一个变量中(这样做的原因是awk返回一个列表,列表,末尾有一个额外的列。当我将列传递给时,我会将逗号“切掉” cut。)

将 的分隔符设置为cut“空格”(-d' '),并将输出列设置为 的逗号分隔列表awk,并将最后一个逗号切掉(-f${cols:0:-1})。

输出:

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

如果要输出少于min1 的列(即第 3、5、6、7 列),只需将上述脚本if中的语句条件反转即可。awkif (count[i] < min)

输出:

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

相关内容