bash
CentOS 시스템의 파일에서 일부 값을 추출 해야 합니다 . myfile.txt
이라는 개체 목록이 있는데 , Info_region
각 개체는 코드(예: 등)로 식별 BARD1_region_005
됩니다 BIRC2_region_002
. 또한 일부 숫자 변수를 보고하는 다른 열도 있습니다. 내 파일에서 동일한 개체(동일한 코드명)가 여러 번 반복될 수 있습니다. 또한 중복되지 않은 모든 대상 코드의 전체 목록이 포함된 파일도 있습니다. list-file.txt에 표시된 대로 각 객체(코드명)가 한 번만 보고되는 output.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
첫 번째 열에 정렬되어 있다고 가정하면 GNU datamash
유틸리티는 데이터 파일에서만 한 번에 이 작업을 수행할 수 있습니다.
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에서 이 작업을 수행하고 싶지 않지만(그러면 안 되지만) 다른 도구를 사용할 의향이 있다고 가정합니다. GNU awk
방법은 다음과 같습니다.
$ 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