提问人:SWK 提问时间:2/9/2023 更新时间:2/10/2023 访问量:175
AWK:在一个字段中打印具有最大值的所有行 每个字段,包括具有最大值的相同行
AWK: print ALL rows with MAX value in one field Per the other field including Identical Rows with Max value
问:
我正在尝试将每列 2 中具有最高值的行保留在每列 1 中,包括具有最大值的相同行,如下面的所需输出。
数据是
a 55
a 66
a 130
b 88
b 99
b 99
c 110
c 130
c 130
所需输出为
a 130
b 99
b 99
c 130
c 130
我可以从这个网站上找到很好的答案,但并不完全针对当前的问题。
awk '{ max=(max>$2?max:$2); arr[$2]=(arr[$2]?arr[$2] ORS:"")$0 } END{ print arr[max] }' file
生成包含相同行的输出,但最大值来自所有行,而不是每列 1。
a 130
c 130
c 130
awk '$2>max[$1] {max[$1]=$2 ; row[$1]=$0} END{for (i in row) print row[i]}' file
输出包括每列 1 的最大值,但不包括具有最大值的相同行。
a 130
b 99
c 130
你能帮我以所需的方式修剪数据吗?甚至上述所有代码都是从您在本网站的问题和答案中获得的。感谢!!非常感谢您的帮助!!
答:
3赞
jared_mamrot
2/9/2023
#1
我过去使用过这种方法:
awk 'NR==FNR{if($2 > max[$1]){max[$1]=$2}; next} max[$1] == $2' test.txt test.txt
a 130
b 99
b 99
c 130
c 130
这需要您两次传入同一个文件(即 awk '...'test.txt test.txt),所以它并不理想,但希望它能提供所需的输出和你的实际数据。
评论
1赞
konsolebox
2/9/2023
接下来应该在外块中,第二行可以简化为 .max[$1] == 2
1赞
jared_mamrot
2/9/2023
你是绝对正确的 - 谢谢你的更正 - 我从更复杂的脚本中改编了这个答案。我现在编辑答案。谢谢@konsolebox
0赞
SWK
2/9/2023
@jared_mamrot 衷心感谢它完美地满足了我的需求,并且为及时的回答和后续评论的编辑留下了深刻的印象。谢谢!
2赞
Andre Wildberg
2/9/2023
#2
另一种使用 .第二个循环应该是轻的,只是重复重复的最大值。awk
% awk 'arr[$1] < $2{arr[$1] = $2; # get max value
co[$1]++; if(co[$1] == 1){x++; id[x] = $1}} # count unique ids
arr[$1] == $2{n[$1,arr[$1]]++} # count repeated max
END{for(i=1; i<=x; i++){
for(j=1; j<=n[id[i],arr[id[i]]]; j++){print id[i], arr[id[i]]}}}' file
a 130
b 99
b 99
c 130
c 130
或者,如果顺序无关紧要
% awk 'arr[$1] < $2{arr[$1] = $2}
arr[$1] == $2{n[$1,arr[$1]]++}
END{for(i in arr){
j=0; do{print i, arr[i]; j++} while(j < n[i,arr[i]])}}' file
c 130
c 130
b 99
b 99
a 130
--编辑--
在附加列中打印数据
% awk 'arr[$1] < $2{arr[$1] = $2}
arr[$1] == $2{n[$1,arr[$1]]++; line[$1,arr[$1],n[$1,arr[$1]]] = $0}
END{for(i in arr){
j=0; do{j++; print line[i,arr[i],j]} while(j < n[i,arr[i]])}}' file
c 130 data8
c 130 data9
b 99 data5
b 99 data6
a 130 data3
数据
% cat file
a 55 data1
a 66 data2
a 130 data3
b 88 data4
b 99 data5
b 99 data6
c 110 data7
c 130 data8
c 130 data9
评论
0赞
SWK
2/9/2023
非常感谢您的帮助!它对我有用。当数据具有多个列时,应如何修改打印选项以打印这些行的所有列?谢谢!
1赞
Andre Wildberg
2/9/2023
@SWK我添加了编辑以获取其他列!
1赞
SWK
2/9/2023
它非常适合我的需求,我也感谢您的及时回复!!
2赞
dawg
2/9/2023
#3
这里有一个红宝石可以做到这一点:
ruby -e '
grps=$<.read.split(/\R/).
group_by{|line| line[/^\S+/]}
# {"a"=>["a 55", "a 66", "a 130"], "b"=>["b 88", "b 99", "b 99"], "c"=>["c 110", "c 130", "c 130"]}
maxes=grps.map{|k,v| v.max_by{|s| s.split[-1].to_f}}
# ["a 130", "b 99", "c 130"]
grps.values.flatten.each{|s| puts s if maxes.include?(s)}
' file
指纹:
a 130
b 99
b 99
c 130
c 130
评论
0赞
SWK
2/9/2023
我将来可能会寻找使用 ruby 的解决方案,并感谢您的代码和解释。
3赞
Ed Morton
2/10/2023
#4
使用任何 awk:
awk '
{ cnt[$1,$2]++; max[$1]=$2 }
END { for (key in max) { val=max[key]; for (i=1; i<=cnt[key,val]; i++) print key, val } }
' file
a 130
b 99
b 99
c 130
c 130
评论
3赞
dawg
2/10/2023
这假定按键升序值排序。可固定或预分拣...file
max[$1]=max[$1] < $2 ? $2 : max[$1]
1赞
Ed Morton
2/10/2023
@dawg,对,根据示例输入。如果没有,那么或按照您所说的进行调整。sort file | awk ...
0赞
SWK
2/10/2023
“ 排序文件 |awk ' { cnt[$1,$2]++; max[$1]=$2 } END { for (key in max) { val=max[key]; for (i=1; i<=cnt[key,val]; i++) print key, val } } ' “ 非常适合我的未排序数据!当函数中没有涉及其他列时,我应该如何修改以打印所有列?非常感谢!!
2赞
Ed Morton
2/10/2023
@SWK问一个新问题,因为这是您在这里提出的问题的一个很好的解决方案,但这不是您评论中问题的正确起点。别客气。
0赞
SWK
2/10/2023
@dawg如果你的意思是这样的修改 '' awk '{ cnt[$1,$2]++; max[$1]=max[$1] < $2 ? $2 : max[$1] } END { for (key in max) { val=max[key]; for (i=1; i<=cnt[key,val]; i++) print key, val } }' file “ ,仍然需要排序文件。我可能错了。谢谢!!!
评论