기존 테이블의 특정 매개변수를 기반으로 새 테이블 만들기

기존 테이블의 특정 매개변수를 기반으로 새 테이블 만들기

테이블에서 여러 개의 개별 CSV 파일을 만들고 싶습니다. 다음은 예시 테이블입니다.

gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
gene1  1            0          0         0         0      0            0          0         0         0
gene2  1            1          1         1         0      0            0          0         0         0
gene3  0            1          0         0         1      0            0          0         0         0
gene4  1            0          0         0         0      1            0          0         0         0
gene5  0            0          0         0         0      1            0          1         0         0
gene6  1            0          0         0         0      0            0          0         1         1
gene7  0            1          0         0         0      0            0          0         0         1

CSV(또는 기타 탭으로 구분된 파일)를 만들고 싶습니다.

  1. "S1"이 포함된 열 헤더 아래에 "1"이 포함된 모든 데이터를 추출하지만, 동일한 유전자의 경우 "S2"가 포함된 모든 헤더의 값은 "0"입니다. 예를 들어:

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene1  1            0          0         0         0      0            0          0         0         0
    gene2  1            1          1         1         0      0            0          0         0         0
    gene3  0            1          0         0         1      0            0          0         0         0
    
  2. REF 파일(S1 또는 S2)에서 값이 "1"인 행만 가져오지만 다른 모든 필드(예: "REF"가 포함되지 않은 행 헤더)에 대해서는 "0"이 있는 행만 가져옵니다. 예를 들어:

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene1  1            0          0         0         0      0            0          0         0         0
    gene4  1            0          0         0         0      1            0          0         0         0
    
  3. 여기서 REF_S1*에는 "1"이 포함됩니다.모두기타(즉, REF가 아닌) S1 샘플은 "0" + 여기서모두REF_S2*는 '0'+이지만 다른 S2 샘플(REF가 아님)은 '1'입니다. 예를 들어:

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene6  1            0          0         0         0      0            0          0         1         1
    gene7  0            1          0         0         0      0            0          0         0         1
    
  4. 마지막으로 모든 *FL은 "1"이고 모든 *호스트는 "0"입니다. 예를 들어:

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene3  0            1          0         0         1      0            0          0         0         0
    gene7  0            1          0         0         0      0            0          0         0         1
    

하지만 어떻게 해야 할지 모르겠습니다. 어떤 제안이라도 환영합니다.

답변1

나는 가정한다

  • (다소) 표시된 것처럼 데이터는 공백으로 구분됩니다.
  • 테이블에는 항상 11개의 열이 있습니다(그러나 행의 수에는 제한이 없을 수 있습니다).
  • 셀 값에는 공백이 포함되지 않습니다. (특히 1행(제목)과 1열(유전자)을 제외한 모든 항목은 0OR  입니다 1.)

로 하는 것은 쉽습니다 awk.

  1. ..."S1"이 포함된 열 헤더 아래에 "1"이 포함된 모든 데이터가 있지만 동일한 유전자의 경우 "S2"가 포함된 모든 헤더의 값은 "0"입니다.

    다시 말해서,

      (2열은 1 OR 3열은 1 OR 4열은 1 OR 5열은 1 OR 6열은 1)
        AND
       7열은 0
        AND
       8열은 0 AND 9   열  은 0
        AND 10열은 0   AND 11열은 0




    그래서,

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1 || $4==1 || $5==1 || $6==1)  &&
                    $7==0 && $8==0 && $9==0 && $10==0 && $11==0 { $1=$1; print }
        '
    
    • OFS"출력 필드 구분 기호"입니다.  입력이 탭으로 구분되거나 공백으로 구분된 경우에도 데이터가 쉼표로 구분된 필드에 기록되도록 -v OFS=','지시합니다 .awk
    • 첫 번째 행(제목 행)을 건너뛰도록 지시합니다 NR==1 { next }. awk머리글 행을 인쇄하려면 으로 변경하세요 NR==1 { $1=$1; print; next }.
    • 다음 두 줄은 위에서 설명한 AND/OR 논리를 인코딩합니다.
    • { $1=$1; print }조건이 충족되면 라인을 인쇄하십시오. 이  $1=$1메서드는 첫 번째 필드를 자신과 동일하게 설정합니다. 아무 일도 일어나지 않을 것처럼 들릴 수도 있습니다. 실제로 awk새로운(사용자 지정) 출력 필드 구분 기호(쉼표로 지정)를 사용하여 행을 강제로 다시 작성하는 것은 트릭입니다. 마음이 바뀌어 입력에 표시된 대로 행을 정확하게 출력하려면  -v OFS=','및 를  제거하십시오 $1=$1;.
  2. ...REF 파일(S1 또는 S2)에 대해 "1" 값이 있고 다른 모든 필드에 대해 "0" 값만 있는 행만...

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1 || $7==1 || $8==1)  &&
                    $4==0 && $5==0 && $6==0 && $9==0 && $10==0 && $11==0 { $1=$1; print }
        '
    
  3. 여기서 REF_S1*에는 "1"이 포함되어 있고 다른 모든(즉, 비REF) S1 샘플은 "0"이고 모든 REF_S2*는 "0"이지만 다른 모든 S2 샘플(비REF)은 "1"입니다.

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1) && $4==0 && $5==0 && $6==0  &&
                    $7==0 && $8==0 && ($9==1 || $10==1 || $11==1) { $1=$1; print }
        '
    
  4. ...모든 *FL은 "1"이고 모든 *호스트는 "0"입니다.

    awk -v OFS=',' '
            NR==1 { next }
            ($3==1 || $6==1 || $8==1 || $11==1)  &&
                    $2==0 && $4==0 && $5==0 && $7==0 && $9==0 && $10==0 { $1=$1; print }
        '
    

답변2

이 문제에 대한 해결책은 다음을 사용하는 것입니다.진주세 단계로 진행하세요.

  • 선택 기준 정규 표현식이 주어지면 기준을 충족하는 필드 번호를 내보내는 서브루틴을 작성하세요.
  • 첫 번째 행이나 헤더 행을 읽을 때 서브루틴을 사용하여 나열된 각 조건에 대한 필드 인덱스를 생성합니다.
  • 마지막으로 이러한 다양한 배열의 도움으로 List::MoreUtils 모듈에서 가져온 함수를 사용하여 부울 선택 기준을 수행합니다.
  • 참고: 원-핫 모드에서는 네 가지 상황을 개별적으로 실행합니다. 그렇지 않으면 출력이 인터리브됩니다.
perl -MList::MoreUtils=any,all -lane '
  BEGIN {
    sub mkAry {
      my $re = shift;
      grep { $_ }
      map { $h{$_} }
      grep { /$re/ } keys %h
    }
  }
  if ($. == 1) {
    print;
    @h{@F} = (0..$#F);
    @S1 = mkAry qr/S1/;
    @S2 = mkAry qr/S2/;
    @REF = mkAry qr/REF/;
    @notREF = mkAry qr/^(?!.*REF)/;
    @REF_S1 = mkAry qr/REF_S1/;
    @REF_S2 = mkAry qr/REF_S2/;
    @notREF_S1 = mkAry qr/^(?!.*REF)(?=.*S1)/;
    @notREF_S2 = mkAry qr/^(?!.*REF)(?=.*S2)/;
    @FL = mkAry qr/FL/;
    @host = mkAry qr/host/;
    next;
  }

  ##_1_:
  print if
    any { $_ == 1 } @F[@S1] and
    all { $_ == 0 } @F[@S2]
  ;

  ##_2_:
  print if
    any { $_ == 1 } @F[@REF] and
    all { $_ == 0 } @F[@notREF]
  ;

  ##_3_:
  print if
    any { $_ == 1 } @F[@REF_S1] and
    all { $_ == 0 } @F[@notREF_S1] and
    all { $_ == 0 } @F[@REF_S2] and
    any { $_ == 1 } @F[@notREF_S2]
  ;

  ##_4_:
  print if
    any { $_ == 1 } @F[@FL] and
    all { $_ == 0 } @F[@host]
  ;
' file | column -t

관련 정보