将列表中的所有值相互乘以的命令?

将列表中的所有值相互乘以的命令?

我有一个数据列表data.txt,如下所示:

Sample A
   12 
   0
   29
   238
   0
   4

基本上它是生物样本(单列)和某些基因的表达(320+ 行)。我想将每行上的每个值相互相乘,这样我就可以得到如下output.txt的结果:

-      -    -      -    -   -
0      -    -      -    -   -
348    0    -      -    -   -
2856   0    82824  -    -   -
0      0    0      0    -   -
48     0    116    952  0   -

我目前只是在 excel 上手动执行此操作,这很痛苦(我是一名生物学家,不太擅长 UNIX 或一般编码)。有什么办法可以用awk(或其他命令)来做到这一点吗?

另外,我实际上有大约 300 个样本(即 300 个单独的data.txt文件),如果我可以为包含所有 300 个样本的文件运行一个脚本(即 300 列、320 行以及每行每列的值),那就更好data.txt了并output.txt为每个样本(列)获取 300 个单独的文件。

答案1

实际上并不难awk,例如,您可以将整个文件放入(1d)数组中,然后对单个数据文件执行双循环:

awk '
  NR > 1 {
    x[NR-1] = $1;
  }
  END {
    for (i=1; ;i++) {
      if (!(i in x))
        break;
      for (j=1; ;j++) {
        if (!(j in x))
          break;
        if (j < i)
          printf "%-6d", x[j]*x[i];
        else
          printf "%-6s", "-";
      }
      printf "\n";
    }
  }
  ' data.txt

请注意,如果您不坚持用破折号填充上三角形,则可以更简单地即时处理线条,即不加载整个文件:

awk '
  NR > 1 {
    x[NR-1] = $1;
    for (j=1;j<NR-1;j++)
      printf "%-6d", $1*x[j];
    printf "%-6s\n", "-";
  }
  ' data.txt
-
0     -
348   0     -
2856  0     6902  -
0     0     0     0     -
48    0     116   952   0     -

如果您的数据集很大,这种方法可能会带来好处(在内存使用方面)。

处理多个文件参数需要一些调整 - 如果您有 GNU awk,您可以使用BEGINFILEENDFILE规则,例如

gawk '
  BEGINFILE {
    delete x;
  }
  FNR > 1 {
    x[FNR-1] = $1;
    next;
  }
  ENDFILE {
    n = length(x);
    for (i=1;i<=n;i++) {
      for (j=1;j<=n;j++) {
        if (j < i)
          printf "%-6d", x[j]*x[i];
        else
          printf "%-6s", "-";
      }
      printf "\n";
    }
    printf "\n";
  }
  ' data1.txt data2.txt

如果没有,gawk您可以通过检查 FNR 何时回滚到 1 来模拟 BEGINFILE/ENDFILE。


但是,如果您的数据集很大,我建议使用为矩阵运算构建的东西,例如 GNU octave(基本上您似乎想要产品的下三角形,对吗?)

您可以在交互式八度解释器中执行此操作,也可以在“批处理”模式下执行此操作,如下所示:

$ octave -q << 'EOF'
> x = textread('data.txt', '%f', 'headerlines', 1);
> M = tril(x * x', -1);
> disp(M);
> EOF
      0      0      0      0      0      0
      0      0      0      0      0      0
    348      0      0      0      0      0
   2856      0   6902      0      0      0
      0      0      0      0      0      0
     48      0    116    952      0      0

根据您的具体输出要求,您可以使用简单的savedlmwrite函数写入M文件,或者fprintf如果您想要真正细粒度的输出格式控制。如果您希望将上面的三角形零替换为破折号,您可能需要查看元胞数组。

答案2

没有一个程序可以执行此特定任务,因此需要一些(初学者级别)编码。

即使可以为此任务编写 awk 脚本,awk 也不是特别适合作为编程语言。 Perl 可能是更适合这项工作的语言,但任何通用编程或脚本语言都可以。由于您不喜欢编码,因此您可能必须找到愿意为您编写程序的人,并将语言的选择权留给他们(除非他们提出的建议需要不成比例的设置工作。)

据我所知,SE 上的答案不应包含特定任务的完整代码,但如果有人发布此类代码,您可能更喜欢他们的答案:-)

相关内容