Awk 将每隔一行生成一个新列
因此,我有一个输出,如下所示:Awk 将每隔一行生成一个新列,awk,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 awk 'NR == 1 { printf "%s %s", $1, $2 for (i = 3; i <= NF; i
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
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 ""
}' "$@"
但是,在下一次分析中,我需要如下所示的输入
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个条件列
从表面上看,“数据是完美的”,无视多年的经验表明数据很少是完美的,那么:
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}
,或者在第一个printf
函数中使用\n\n
代替\n
)。如果愿意,可以将输出字段安排为用制表符分隔(在本代码中,它们用双空格分隔)
代码不依赖于分隔数据字段的选项卡;这只取决于字段中没有空格
许多条件列
当有许多条件列时,需要使用数组和循环来捕获和打印数据,如下所示:
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
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 ""
}' "$@"
awk'NR==1{printf”%s%s“,$1,$2
对于(i=3;i一个简单的解决方案(没有输出头)和(这是一个很好的文本文件“命令行”工具):
首先,使用grep
跳过所有空行,然后使用datamash
根据第一个字段(-g1
)分组行,使用空格作为字段分隔符(-W
),将字段3、4和5的多行折叠在一个组中。折叠的值以逗号分隔,这就是为什么我们必须用tr
将其拆分
对于不同数量的列,只需调整collapse
操作的范围(例如collapse 3-1000
)。由于分组操作,每个组的样本数都已得到支持。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
awk'{k=$1fs$2}
NR==1{p0=$0;pk=k}
pk==k{split(p0,a);for(i=3;i)我们可以假设数据是完美的,总是有两行的倍数,相邻的对总是有相同的样本和pops值(或者,如果它们不同,差异不重要)?是的。数据是完美的。好的;它包括标题行和标题后的空行?列标签是否由制表符分隔?如果不是,则“条件1”等中的空格是讨厌的。所有内容都是制表符分隔的,条件名称将有一个u而不是一个空格。很抱歉,将在问题中解决它事实上,我有超过10列。我刚刚编辑了这个问题。谢谢。100个样本不是问题。1000个条件更接近问题;如果你运气不好,你可能会在你的Awk变体中遇到限制。如果你使用GNU Awk,你可能会没事,也许我在恶意攻击系统。但是要小心一点。我会更新以处理更多的列。thi它工作得很好!命名条件很简单!从未使用过datamash,因此我无法使其真正工作…”datamash:第2行字段2中的数值无效:“轨迹1_35'”看起来您有两行标题,字段2中有字母。max
运算符仅对数字有效,我在这里使用它只是为了传播值(因为每个组都应该是唯一的)。请先尝试使用而不是max
(请参见我的编辑)。此外,您可以使用tail-n+3文件而不是grep
来切掉两行标题。在这种情况下,您不需要-标题在中,即:tail-n+3文件| datamash-W-g1 first 2 collapse 3-5 | tr',''''''| column-t
顺便说一句,您会发现datamash
对于此类简单的统计分析非常有用文本文件。所有这些都可以在awk
和python
中完成,但它通常是与datamash
的一行代码。。。