将同一ID的多个数据项转换为行awk
我有以下格式的数据:将同一ID的多个数据项转换为行awk,awk,Awk,我有以下格式的数据: ID Date X1 X2 X3 1 01/01/00 1 2 3 1 01/02/00 7 8 5 2 01/03/00 9 7 1 2 01/04/00 1 4 5 我想根据ID将测量值分组到新行中,因此我最终得到: ID Date X1 X2 X3 Date X1_2 X2_2 X3_2 1 01/01/00 1 2 3 01/02/00 7 8 5 2 01/03/00 9 7 1 01/04/00 1
ID Date X1 X2 X3
1 01/01/00 1 2 3
1 01/02/00 7 8 5
2 01/03/00 9 7 1
2 01/04/00 1 4 5
我想根据ID将测量值分组到新行中,因此我最终得到:
ID Date X1 X2 X3 Date X1_2 X2_2 X3_2
1 01/01/00 1 2 3 01/02/00 7 8 5
2 01/03/00 9 7 1 01/04/00 1 4 5
等等
对于一个给定的ID,我有多达20个观察结果
到目前为止,我已经尝试了
到目前为止,我尝试的代码是:
awk -F, OFS = '\t' 'NR >1 {a[$1] = a[$1]; a[$2] = a[$2]; a[$3] = a[$3];a[$4] = a[$4]; a[$5] = a[$5] OFS $5} END {print "ID,Date,X1,X2,X3,Date_2,X1_2, X2_2 X3_2'\t' for (ID in a) print a[$1:$5] }' file.txt
该文件是以制表符分隔的文件。我不知道如何处理数据,也不知道如何解释每个人会有两个以上的观察结果。只需跟踪上一个字段。如果更改,请打印存储的行:
awk 'NR==1 {print; next} # print header
prev && $1!=prev {print prev, line; line=""} # print on different $1
{prev=$1; $1=""; line=line $0} # store data and remove $1
END {print prev, line}' file # print trailing line
如果有制表符分隔的字段,只需添加-F“\t”
试验
您可以试试这个(gnu awk解决方案)
gawk'
NR==1{
N=NF;
MAX=NF-1;
对于(i=1;我/我想知道gsub(“^”$1 FS,””)
是否可以。有没有更好的方法删除第一个字段?1=“”
,它可以保持FS的位置,所以我想你也可以合并line=line$0
。@karakfa不是真的。Testecho“你好”| awk'{$1=“”;print}“
你会看到一个领先的FS在左边。是的,这正是我的意思。它将保留FS,这样你就可以用line=line FS$0
更改line=line$0
@karakfa aaah这很聪明,现在我明白了。谢谢,更新我的答案:)
$ awk 'NR==1 {print; next} prev && $1!=prev {print prev, line; line=""} {prev=$1; $1=""; line=line $0} END {print prev, line}' a
ID Date X1 X2 X3
1 01/01/00 1 2 3 01/02/00 7 8 5
2 01/03/00 9 7 1 01/04/00 1 4 5
gawk '
NR == 1 {
N = NF;
MAX = NF-1;
for(i=1; i<=NF; i++){ #store columns names
names[i]=$i;
}
next;
}
{
for(i=2; i<=N; i++){
a[$1][length(a[$1])+1] = $i; #store records for each id
}
if(length(a[$1])>MAX){
MAX = length(a[$1]);
}
}
END{
firstline = names[1];
for(i=1; i<=MAX; i++){ #print first line
column = int((i-1)%(N-1))+2
count = int((i-1)/(N-1));
firstline=firstline OFS names[column];
if(count>0){
firstline=firstline"_"count
}
}
print firstline
for(id in a){ #print each record in store
line = id;
for(i=1; i<=length(a[id]); i++){
line=line OFS a[id][i];
}
print line;
}
}
' input
ID Date X1 X2 X3
1 01/01/00 1 2 3
1 01/02/00 7 8 5
2 01/03/00 9 7 1
2 01/04/00 1 4 5
1 01/03/00 72 28 25
ID Date X1 X2 X3 Date_1 X1_1 X2_1 X3_1 Date_2 X1_2 X2_2 X3_2
1 01/01/00 1 2 3 01/02/00 7 8 5 01/03/00 72 28 25
2 01/03/00 9 7 1 01/04/00 1 4 5