在UNIX中执行GROUP BY-like命令


0

我有一个如下文本文件:

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。

我想要做的是找出哪些列让我们说不到2 1。例如,在我上面的矩阵中,我想摆脱第3,5,6和7列,因为它们只有一个1。

是否有UNIX命令来执行此操作?可能我需要一个Group by-like(SQL)命令,然后跟踪哪些列小于一定数量,但我不知道如何做到这一点。


不。如果你正在切换 那个&lt; 2 1s,那就没问题了。最初的问题需要一些编程。
johntellsall

Answers:


1

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

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
}

如果使用执行此脚本

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 返回带有额外内容的列列表 , 在末尾。当我将cols传递给我时,我将“逗号”切掉 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

如果要输出少于的列 min 1s(即第3,5,6,7列),只是反转了条件 if 声明中 awk 上面的脚本阅读 if (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

感谢那。实际上代码可能有一些问题。什么是NR!= 1部分?编辑:它适用于NR> 0。
ddmichael

@ddmichael NR != 1 用于跳过带有列编号的标题行。它说“如果记录号(NR)不是1,那么请执行以下操作。”在我的系统上 NR > 1 也有效,但是 NR > 0。我很惊讶它适合你 - 也许是你的 awk 从零开始编号?
savanto

啊,是的,你是对的。
ddmichael
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.