将每隔一行放入一个新列

时间:2017-11-16 20:11:07

标签: awk

所以,我的输出看起来像这样:

samples pops    condition 1     condition 2 condition 3

A10051  15  1   3   4   
A10051  15  2   4   4   
A10052  15  2   1   4   
A10052  15  2   1   4

然而,对于下一次分析,我需要输入看起来像这样

samples pops    condition 1     condition 1     condition 2     condition 2 condition 3 condition 3

A10051  15  1   2   3   4   4   4       
A10052  15  2   2   1   1   4   4   

因此,不仅要使每个其他行都是新列,给定列中的每一行都将在分配给相同条件的新列中,每个样本都有两列用于相同条件而不是同一样品的两行。例如,我放了2个样本和3个条件,但是IRL我有超过100个样本和超过1000个条件...... 有什么想法吗?我相信它可以用awk完成,但我无法弄明白。

3 个答案:

答案 0 :(得分:2)

3个条件列

以表面价值断言“数据是完美的”,并且无视多年的经验表明数据很少是完美的,那么:

awk 'NR == 1 { printf "%s  %s  %s  %s  %s  %s  %s  %s\n",
                      $1, $2, $3, $3, $4, $4, $5, $5; next }
     NR == 2 { next }
     NR % 2 == 1 { c[1] = $3; c[2] = $4; c[3] = $5 }
     NR % 2 == 0 { printf "%s  %d  %d  %d  %d  %d  %d  %d\n",
                          $1, $2, c[1], $3, c[2], $4, c[3], $5 }' "$@"

给定输入文件:

samples pops    condition_1     condition_2 condition_3

A10051  15  1   3   4
A10051  15  2   4   4
A10052  15  2   1   4
A10052  15  2   1   4

脚本生成输出:

samples  pops  condition_1  condition_1  condition_2  condition_2  condition_3  condition_3
A10051  15  1  2  3  4  4  4
A10052  15  2  2  1  1  4  4

这段代码比机械更有趣。如果每行有10列,则以不同的方式处理它。您可能使用循环来保存和打印数据。如果您希望标题和数据之间有空行,则可以在第一个NR == 2 { print; next }函数中轻松添加一个(\n\n或使用\n代替printf。如果您愿意,可以安排输出字段由制表符分隔(在此代码中它们用双空格分隔)。

代码不依赖于分隔数据字段的选项卡;它只取决于场内没有空白区域。

许多条件列

当有许多条件列时,您需要使用数组和循环来捕获和打印数据,如下所示:

awk 'NR == 1 { printf "%s  %s", $1, $2
               for (i = 3; i <= NF; i++) printf "  %s  %s", $i, $i
               print ""
               next
             }
     NR == 2 { next }
     NR % 2 == 1 { for (i = 3; i <= NF; i++) c[i] = $i }
     NR % 2 == 0 { printf "%s  %d", $1, $2;
                   for (i = 3; i <= NF; i++) printf "  %d  %d", c[i], $i
                   print ""
                 }' "$@"

当运行与之前相同的数据时,它产生与以前相同的输出,但循环将允许它读取每个输入行的1000个条件并为每个输出行生成2000个条件。唯一可能的问题是你的awk版本是否首先处理这么长的输入行。如果需要,请升级到GNU Awk。

答案 1 :(得分:2)

使用GNU datamash的简单解决方案(无输出标头)(这是文本文件中“命令行statistical operations ”的一个很好的工具):

$ grep -v ^$ file | datamash -W -g1 --header-in first 2 collapse 3-5 | tr ',' ' ' | column -t
A10051  15  1  2  3  4  4  4
A10052  15  2  2  1  1  4  4

首先,使用grep跳过所有空行,然后根据第一个字段(datamash)使用-g1组行,使用空格作为字段分隔符({{1对于字段3,4和5,折叠组中的多个行。折叠值以逗号分隔,这就是为什么我们必须使用-W打破它们。

对于不同数量的列,只需调整tr操作的范围(例如collapse)。由于分组操作,已经支持每组的任意数量的样本。

答案 2 :(得分:1)

awk救援!

awk     '{k=$1 FS $2} 
   NR==1 {p0=$0; pk=k}
   pk==k {split(p0,a); for(i=3;i<=NF;i++) $i=a[i] FS $i; print}
   pk!=k {p0=$0; pk=$1 FS $2}' file

samples pops condition_1 condition_1 condition_2 condition_2 condition_3 condition_3
A10051 15 1 2 3 4 4 4
A10052 15 2 2 1 1 4 4

将适用于未指定数量的列和记录,只要它们都是格式正确(相同数量的列)和分组(相同的键按顺序)。