테이블 열을 행으로 변환하는 방법은 무엇입니까?

테이블 열을 행으로 변환하는 방법은 무엇입니까?

두 개의 열이 있는 탭으로 구분된( ) 파일이 있습니다 \t.

a_1  T_b
a_2  T_c
a_2  T_d
a_2  T_e
a_3  T_f
a_4  B_a
a_4  B_b

이제 이것을 한 줄에 하나의 샘플이 있는 파일로 변환하고 싶습니다. 각 샘플의 모든 값은 다음과 같이 같은 줄에 공백으로 구분된 세 번째 필드입니다.

a_1  T_b
a_2  T_c T_d T_e
a_3  T_f 
a_4  B_a B_b

방금 두 번째 파일에서 첫 번째 파일로의 awk 변환을 마스터했습니다. 그러니 제게 조언을 좀 해주시고 저의 부족한 유닉스 기술을 용서해 주십시오. 감사합니다.

답변1

datamash첫 번째 탭으로 구분된 열을 기준으로 그룹화하고 GNU를 사용하여 다른 열을 축소합니다.

$ datamash groupby 1 collapse 2 <file
a_1     T_b
a_2     T_c,T_d,T_e
a_3     T_f
a_4     B_a,B_b

이는 파일이 첫 번째 필드를 기준으로 정렬되어 있다고 가정합니다. 그렇지 않은 경우 datamash해당 -s( ) 옵션을 사용하거나 를 통해 --sort데이터를 파이프하십시오 .datamashsort

두 번째 필드의 "하위 필드"를 쉼표 대신 공백으로 구분하려면 다음 명령을 사용하여 쉼표를 공백으로 바꾸십시오 awk.

$ datamash groupby 1 collapse 2 <file | awk -F '\t' 'BEGIN { OFS=FS } { gsub(","," ",$2) }; 1'
a_1     T_b
a_2     T_c T_d T_e
a_3     T_f
a_4     B_a B_b

답변2

한 가지 방법은 다음과 같습니다.

$ awk -F'\t' '
      { 
        $1 in a? a[$1]=a[$1]" "$2 : a[$1]=$2 
      }
      END{ 
        for(i in a){print i"\t"a[i]} 
      }' file

a_1 T_b
a_2 T_c T_d T_e
a_3 T_f
a_4 B_a B_b

여기서의 아이디어는 a키가 샘플 이름인 첫 번째 필드인 연관 배열을 생성한다는 것입니다. 그런 다음 각 행에 대해 해당 샘플이 이미 키로 존재하는 경우 해당 값을 행의 두 번째 필드에 설정하고, 그렇지 않은 경우 현재 두 번째 필드를 기존 값에 추가합니다. 동일한 내용을 다음과 같이 더 자세히 작성할 수 있습니다.

$ awk -F'\t' '
      { 
        if($1 in a){ a[$1]=a[$1]" "$2 }
        else       { a[$1]=$2 }
      }
      END{ 
        for(i in a){print i"\t"a[i]} 
      }' file

답변3

Raku(이전 Perl_6) 사용

raku -e 'my %hash; for lines>>.words() {%hash.append( .[0] => .[1] )}; .say for %hash.sort;' 

또는

raku -e 'my %hash; for lines.map(*.words) -> ($k,$v) {%hash.append: $k => $v }; .say for %hash.sort;' 

간단히 말해서, Raku에 내장된 해싱 기능이 이 문제를 해결하는 데 사용됩니다. 행을 읽고 (공백으로 구분) 으로 분할합니다 words. 단어는 해시에 추가되며 %hash첫 번째 열은 키가 되고 두 번째 열은 값이 됩니다. Raku의 =>"fat arrow" 연산자는 키-값 쌍을 구성하는 데 사용되며 append루틴은 키를 기반으로 값을 누적합니다(해시는 중복 키를 가질 수 없습니다).

입력 예:

a_1  T_b
a_2  T_c
a_2  T_d
a_2  T_e
a_3  T_f
a_4  B_a
a_4  B_b

예제 출력:

a_1 => T_b
a_2 => [T_c T_d T_e]
a_3 => T_f
a_4 => [B_a B_b]

.say.put탭으로 구분된 출력을 얻으 려면 위의 코드를 변경하세요 \t. 또는 자신만의 필드 구분 기호를 정의하세요. 아래 예에서 첫 번째와 두 번째 열은 4개의 공백으로 구분되고 value두 번째 열은 쉼표로 구분됩니다(필요한 경우 공백으로 변경).

~$ raku -e 'my %hash; for lines.map(*.words) -> ($k,$v) {%hash.append: $k => $v }; for %hash.sort {put .key, "    ", .value.join(",")};'
a_1    T_b
a_2    T_c,T_d,T_e
a_3    T_f
a_4    B_a,B_b

https://docs.raku.org/언어/hashmap#Mutable_hashes_and_immutable_maps
https://docs.raku.org/routine/=%3E
https://raku.org

관련 정보