공개 식별자의 시작 및 끝 위치 추출

공개 식별자의 시작 및 끝 위치 추출

다음과 같은 파일이 있습니다.

Id       Chr     Start   End  
Prom_1   chr1    3978952 3978953  
Prom_1   chr1    3979165 3979166  
Prom_1   chr1    3979192 3979193  
Prom_2   chr1    4379047 4379048  
Prom_2   chr1    4379091 4379092  
Prom_2   chr1    4379345 4379346  
Prom_2   chr1    4379621 4379622  
Prom_3   chr1    5184469 5184470  
Prom_3   chr1    5184495 5184496  

내가 추출하고 싶은 것은 다음과 같이 시작과 끝이 동일합니다 Id.

Id       Chr     Start   End  
Prom_1   chr1    3978952 3979193  
Prom_2   chr1    4379047 4379622  
Prom_3   chr1    5184469 5184496

아시다시피, 반복 횟수는 Id시작과 끝 사이에 일정하지 않습니다. 어떤 아이디어라도 크게 감사하겠습니다.

답변1

GNU와 함께데이터 혼합:

datamash -H -W -g 1,2 min 3 max 4 <input

답변2

이것은 awk를 사용하여 파일을 읽거나 다른 방법을 사용하는 전통적인 루프를 통해 수행될 수 있지만 awk 기반 솔루션을 제공하기에는 awk에 능숙하지 않습니다. 다음 솔루션은 bash에서 잘 작동하며 간단한 awk, grep 및 배열을 사용합니다.

알려진 ID가 있음(매개변수 또는 사용자 입력을 통해)

id="Prom_1" #Or for user input read -p "Give Id :" id
header=$(head -1 a.txt) #get the 1st line and store it as header.
data=($(grep $id a.txt)) #grep the file for given the id and fill an array
echo "$header"
echo -e "${data[0]}\t${data[1]}\t${data[2]}\t${data[-1]}" #data[-1] refers to the last element of the data array
#Output:
Id       Chr     Start   End  
Prom_1  chr1    3978952 3979193

비결은 배열이 공백(기본 IFS)으로 구분된 모든 grep 값을 가져오므로 배열은 다음과 같습니다.

root@debi64:# id="Prom_1";data=($(grep $id a.txt));declare -p data
declare -a data=([0]="Prom_1" [1]="chr1" [2]="3978952" [3]="3978953" [4]=$'\nProm_1' [5]="chr1" [6]="3979165" [7]="3979166" [8]=$'\nProm_1' [9]="chr1" [10]="3979192" [11]="3979193")
#declare -p command just prints out all the data of the array (keys and values)

파일에서 ID를 자동으로 검색하려면 다음과 같이 uniq prog를 사용할 수 있습니다.

readarray -t ids< <(awk -F" " '{print $1}' a.txt |uniq |tail -n+2) 
#For Field separator= " " print the first field (id), print them as unique fields and store them in an array.
#Here the use of readarray is better to handle data separated by new lines.
declare -p ids
#Output: declare -a ids=([0]="Prom_1" [1]="Prom_2" [2]="Prom_3")

함께 모아서:

header=$(head -1 a.txt) #get the 1st line and store it as header.
readarray -t ids< <(awk -F" " '{print $1}' a.txt |uniq |tail -n+2)
echo "$header"
for id in ${ids[@]}
do
data=($(grep $id a.txt))
echo -e "${data[0]}\t${data[1]}\t${data[2]}\t${data[-1]}"
done 

#Output 
Id       Chr     Start   End  
Prom_1  chr1    3978952 3979193
Prom_2  chr1    4379047 4379622
Prom_3  chr1    5184469 5184496

답변3

이거 좀 시도해 볼 수 있어?

$ awk 'NR==1{print; next}NR!=1{if(!($1 in Arr)){printf("\t%s\n%s\t%s\t%s",a,$1,$2,$3);Arr[$1]++}else{a=$NF}}END{printf("\t%s\n",a)}' input.txt
Id       Chr     Start   End

Prom_1  chr1    3978952 3979193
Prom_2  chr1    4379047 4379622
Prom_3  chr1    5184469 5184496

awk '
NR==1{print; next}
NR!=1{
if(!($1 in Arr))
{
       printf("\t%s\n%s\t%s\t%s",a,$1,$2,$3);Arr[$1]++;
}
else
{
    a=$NF
}
}
END{
printf("\t%s\n",a)
}' input.txt

답변4

awk를 사용하고 변수에 저장하는 또 다른 솔루션:

파일의 헤더를 가져와서 출력 파일에 넣습니다.

row1=$(head -1 input_file)
echo $row1 | sed -e 's/ /\t/g' > output_file

첫 번째 열의 고유 값을 가져옵니다.

col1=$(for i in $(awk 'NR>1 {print $1}' input_file | uniq); do echo $i; done)

각 첫 번째 열 값에 대해 두 번째 행의 값이 처음으로 나타나는 것을 가져옵니다.

col2=$(for i in $(echo "$col1"); do grep -m1 $i input_file | awk '{print $2}'; done)

각 첫 번째 열 값을 기반으로 세 번째 열의 첫 번째 값을 가져옵니다.

col3=$(for i in $(echo "$col1"); do grep -m1 $i input_file | tail -1 | awk '{print $3}'; done)

각 첫 번째 열 값을 기반으로 네 번째 열의 마지막 값을 가져옵니다.

col4=$(for i in $(echo "$col1"); do grep $i input_file | tail -1 | awk '{print $4}'; done)

다음 값을 모두 출력 파일에 추가합니다.

paste -d'\t' <(echo "$col1") <(echo "$col2") <(echo "$col3") <(echo "$col4") >> output_file

관련 정보