我有一个数据列表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,您可以使用BEGINFILE
和ENDFILE
规则,例如
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
根据您的具体输出要求,您可以使用简单的save
或dlmwrite
函数写入M
文件,或者fprintf
如果您想要真正细粒度的输出格式控制。如果您希望将上面的三角形零替换为破折号,您可能需要查看元胞数组。
答案2
没有一个程序可以执行此特定任务,因此需要一些(初学者级别)编码。
即使可以为此任务编写 awk 脚本,awk 也不是特别适合作为编程语言。 Perl 可能是更适合这项工作的语言,但任何通用编程或脚本语言都可以。由于您不喜欢编码,因此您可能必须找到愿意为您编写程序的人,并将语言的选择权留给他们(除非他们提出的建议需要不成比例的设置工作。)
据我所知,SE 上的答案不应包含特定任务的完整代码,但如果有人发布此类代码,您可能更喜欢他们的答案:-)