목록의 모든 값을 서로 곱하는 명령?

목록의 모든 값을 서로 곱하는 명령?

다음과 같은 데이터 목록이 있습니다 data.txt.

Sample A
   12 
   0
   29
   238
   0
   4

기본적으로 생물학적 샘플(단일 열)과 특정 유전자의 발현(320개 이상의 행)입니다. 각 행의 각 값을 서로 곱하여 output.txt다음과 같은 결과를 얻고 싶습니다 .

-      -    -      -    -   -
0      -    -      -    -   -
348    0    -      -    -   -
2856   0    82824  -    -   -
0      0    0      0    -   -
48     0    116    952  0   -

저는 현재 Excel에서 수동으로 이 작업을 수행하고 있는데 이는 고통스럽습니다. (저는 생물학자이고 UNIX나 코딩 전반에 능숙하지 않습니다.) awk(또는 다른 명령을) 사용하여 이를 수행할 수 있는 방법이 있습니까 ?

또한 실제로 약 300개의 샘플(즉, 300개의 개별 파일)이 있는데 data.txt, 300개의 샘플(즉, 300개 열, 320개 행, 각 행과 열의 값)이 모두 포함된 파일에 대해 스크립트를 실행할 수 있다면 더 좋은 점은 data.txtoutput.txt샘플(열)에 대해 300개의 개별 파일을 얻는 것입니다.

답변1

실제로 그렇게 어렵지는 않습니다 awk. 예를 들어 전체 파일을 (1d) 배열에 넣고 단일 데이터 파일에 대해 이중 루프를 수행할 수 있습니다.

awk '
  NR > 1 {
    x[NR-1] = $1;
  }
  END {
    for (i=1; ;i++) {
      if (!(i in x))
        break;
      for (j=1; ;j++) {
        if (!(j in x))
          break;
        if (j < i)
          printf "%-6d", x[j]*x[i];
        else
          printf "%-6s", "-";
      }
      printf "\n";
    }
  }
  ' data.txt

위쪽 삼각형을 대시로 채우려고 하지 않으면 즉시 선을 사용하여 작업하는 것이 더 쉽습니다.즉, 전체 파일을 로드하지 않습니다.

awk '
  NR > 1 {
    x[NR-1] = $1;
    for (j=1;j<NR-1;j++)
      printf "%-6d", $1*x[j];
    printf "%-6s\n", "-";
  }
  ' data.txt
-
0     -
348   0     -
2856  0     6902  -
0     0     0     0     -
48    0     116   952   0     -

데이터 세트가 큰 경우 이 접근 방식은 메모리 사용량 측면에서 이점을 제공할 수 있습니다.

여러 파일 인수를 처리하려면 약간의 조정이 필요합니다. GNU awk가 있으면 다음과 같은 규칙을 사용할 수 BEGINFILE있습니다 ENDFILE.

gawk '
  BEGINFILE {
    delete x;
  }
  FNR > 1 {
    x[FNR-1] = $1;
    next;
  }
  ENDFILE {
    n = length(x);
    for (i=1;i<=n;i++) {
      for (j=1;j<=n;j++) {
        if (j < i)
          printf "%-6d", x[j]*x[i];
        else
          printf "%-6s", "-";
      }
      printf "\n";
    }
    printf "\n";
  }
  ' data1.txt data2.txt

그렇지 않은 경우 gawkFNR이 1로 롤백되는 시점을 확인하여 BEGINFILE/ENDFILE을 시뮬레이션할 수 있습니다.


그러나 데이터 세트가 크다면 GNU와 같은 행렬 연산용으로 구축된 것을 사용하는 것이 좋습니다 octave(기본적으로 제품의 아래쪽 삼각형을 원하는 것 같죠?)

대화형 Octave 인터프리터 또는 다음과 같이 "배치" 모드에서 이 작업을 수행할 수 있습니다.

$ octave -q << 'EOF'
> x = textread('data.txt', '%f', 'headerlines', 1);
> M = tril(x * x', -1);
> disp(M);
> EOF
      0      0      0      0      0      0
      0      0      0      0      0      0
    348      0      0      0      0      0
   2856      0   6902      0      0      0
      0      0      0      0      0      0
     48      0    116    952      0      0

특정 출력 요구 사항에 따라 간단한 save또는 기능을 사용하여 파일 dlmwrite에 쓸 수 있거나 매우 세밀한 출력 형식 제어를 원할 경우 사용할 수 있습니다. 위의 삼각형 0을 대시로 바꾸려면 셀 배열을 살펴보는 것이 좋습니다.Mfprintf

답변2

이 특정 작업을 수행할 수 있는 단일 프로그램이 없으므로 일부(초급 수준) 코딩이 필요합니다.

이 작업을 위해 awk 스크립트를 작성하는 것이 가능하더라도 awk는 프로그래밍 언어로 특별히 적합하지 않습니다. Perl이 해당 작업에 더 나은 언어일 수 있지만 범용 프로그래밍이나 스크립팅 언어라면 모두 가능합니다. 당신은 코딩을 좋아하지 않기 때문에 당신을 위해 프로그램을 작성하고 언어 선택을 그들에게 맡겨줄 누군가를 찾아야 할 것입니다(그들의 제안이 너무 많은 설정 노력을 요구하지 않는 한).

내가 아는 한 SE의 답변에는 특정 작업에 대한 완전한 코드가 포함되어서는 안 되지만, 누군가 그러한 코드를 게시하면 귀하는 그 사람의 답변을 선호할 수도 있습니다. :-)

관련 정보