我需要从bash
CentOS 系统上的文件中提取一些值。我myfile.txt
有一个被调用的对象列表Info_region
,其中每个对象都用代码(例如BARD1_region_005
或BIRC2_region_002
等)标识。此外,还有一些其他列报告了一些数值变量。相同的对象(相同的代码名称)可以在我的文件中重复多次。我还有一个文件,其中包含完整的列表,其中包含所有目标代码,没有重复项。我想获得一个output.txt 文件,其中每个对象(代码名)仅报告一次,如我的list-file.txt 中所示,并且我想将与myfile 中该代码名关联的最大可能值关联到此文件。 TXT。
myfile.txt:(列由 分隔tab
)
Info_region Lig_score Lig_prevista Lig_prevista_+1 Int_score Expo_score Protac_score
BARD1_region_005 0 3 3 0 1 1
BARD1_region_006 0 1 1 0 1 1
BIRC2_region_001 1 6 7 0 1 2
BIRC2_region_001 1 7 8 0 1 2
BIRC2_region_001 0 2 2 0 0 0
BIRC2_region_001 0 12 12 0 1 1
BIRC2_region_001 1 10 11 -1 1 1
BIRC2_region_001 1 2 3 0 1 2
BIRC2_region_001 1 0 1 0 1 2
BIRC2_region_001 1 6 7 0 1 2
BIRC2_region_002 0 0 0 0 1 1
BIRC2_region_002 1 0 0 -1 0.5 0.5
BIRC2_region_003 0 0 0 0 1 1
BIRC2_region_004 0 1 1 0 1 1
UHRF1_region_004 0 0 0 1 1 2
UHRF1_region_004 0 0 0 1 1 2
UHRF1_region_004 1 0 1 0 0.5 1.5
UHRF1_region_004 0 0 0 1 1 2
UHRF1_region_005 0 3 3 1 1 2
UHRF1_region_005 1 0 0 -1 1 1
文件列表.txt:
Info_region
BARD1_region_005
BARD1_region_006
BIRC2_region_001
BIRC2_region_002
BIRC2_region_003
BIRC2_region_004
UHRF1_region_004
UHRF1_region_005
输出.txt:
Info_region Lig_score Lig_prevista Lig_prevista_+1 Int_score Expo_score Protac_score
BARD1_region_005 0 3 3 0 1 1
BARD1_region_006 0 1 1 0 1 1
BIRC2_region_001 1 12 12 0 1 2
BIRC2_region_002 1 0 0 0 1 1
BIRC2_region_003 0 0 0 0 1 1
BIRC2_region_004 0 1 1 0 1 1
UHRF1_region_004 1 0 1 1 1 2
UHRF1_region_005 1 3 3 1 1 2
有人可以帮我吗?谢谢你!
答案1
假设数据位于被调用的文件中file
并且在第一列上排序,GNUdatamash
实用程序可以单独对数据文件一次性执行此操作:
datamash -H -W -g 1 max 2-7 <file
这指示实用程序使用空格分隔的列(-W
;如果您的列确实是制表符分隔的,则删除此列),数据的第一行包含标题 ( -H
),按第一列 ( ) 进行分组-g 1
,并计算最大值从第 2 列到第 7 列。
考虑到问题中的数据,结果:
GroupBy(Info_region) max(Lig_score) max(Lig_prevista) max(Lig_prevista_+1) max(Int_score) max(Expo_score) max(Protac_score)
BARD1_region_005 0 3 3 0 1 1
BARD1_region_006 0 1 1 0 1 1
BIRC2_region_001 1 12 12 0 1 2
BIRC2_region_002 1 0 0 0 1 1
BIRC2_region_003 0 0 0 0 1 1
BIRC2_region_004 0 1 1 0 1 1
UHRF1_region_004 1 0 1 1 1 2
UHRF1_region_005 1 3 3 1 1 2
您还可以使用--header-in
in 来-H
获取无标头输出,然后从原始数据文件中获取标头:
{ head -n 1 file; datamash --header-in -W -g 1 max 2-7 <file; } >output
在这里,我还将结果写入一些名为output
.
使用awk
并假设制表符分隔字段:
awk -F '\t' '
BEGIN { OFS = FS }
NR == 1 { print; next }
{
n[$1] = 1
for (i = 2; i <= NF; ++i)
a[$1,i] = (a[$1,i] == "" || $i > a[$1,i] ? $i : a[$1,i])
}
END {
nf = NF
for (j in n) {
$0 = j
for (i = 2; i <= nf; ++i)
$i = a[$1,i]
print
}
}' file
这将计算每组每列中的最大值。这些数字存储在a
数组中,而n
数组仅将组名称作为键保存。
答案2
我假设您实际上不想在 bash 中执行此操作(而且您不应该这样做),但愿意使用其他工具。这是一个 GNUawk
方法:
$ gawk -vOFS="\t" -F'\t' \
'{
if(NR==1){print; }
else{
for(i=2;i<=NF;i++){
if($i > a[$1][i] || ! a[$1][i]){a[$1][i]=$i}
}
}
}
END{
for (region in a){
printf "%s", region;
for(i=2;i<=NF;i++){
printf "%s%s", OFS,a[region][i]
}
printf "\n";
}
}' myfile.txt
Info_region Lig_score Lig_prevista Lig_prevista_+1 Int_score Expo_score Protac_score
BIRC2_region_001 1 12 12 0 1 2
BIRC2_region_002 1 0 0 -1 1 1
BIRC2_region_003 0 0 0 0 1 1
BIRC2_region_004 0 1 1 0 1 1
BARD1_region_005 0 3 3 0 1 1
BARD1_region_006 0 1 1 0 1 1
UHRF1_region_004 1 0 1 1 1 2
UHRF1_region_005 1 3 3 1 1 2
答案3
这是一种既不使用真正的多维数组也不使用模拟多维的方法。相反,我们将块存储在同一个键中。
awk '
BEGIN { OFS = FS = "\t" }
NR==1 { print; next }
{
obj = $1; $1=""; sub(FS, "")
a[obj] = a[obj] $0 FS
}
END {
nf0 = NF
for (obj in a) {
$1 = obj
nf = split(a[obj], f)
for (i=1; i<=nf0; i++) {
$(i+1) = f[i]
for (j=0; j<int(nf/nf0); j++) {
idx = i + nf0*j
if ( f[idx] > $(i+1) ) $(i+1) = f[idx]
}
}
print
}
}
' myfile.txt