점수를 기반으로 데이터 확장

점수를 기반으로 데이터 확장

먼저 3개 열의 유효한 조합 세트(validlist)가 있으므로 최종 결과는 해당 파일의 하위 집합이어야 합니다.

a   b   c
c   b   c
p   b   d
d   y   d
p   y   d
x   y   z

아래와 같이 점수 행렬(점수 파일)이 있습니다. 여기서 세 번째 열(최대 1, 최소 0)은 두 번째 열 변수가 첫 번째 열 변수에 얼마나 가까운지를 나타냅니다.

a       b       0.3
a       c       0.87
a       d       0.75
b       x       0.87
b       y       0.98
b       z       0.24
c       m       0.9
c       n       0.86
d       p       0.87

변수 집합이 주어지면 주어진 열 변수에 매우 가까운(> 0.7) 다른 조합으로 선택을 확장해야 하며 근접성 합계는 1.6보다 큽니다. .

예를 들어 변수 a는 a-점수 > 0.7이므로 변수 c와 d를 포함하도록 확장될 수 있습니다.

변수 b는 y를 포함하도록 확장될 수 있고, c는 m과 n을 포함할 수 있습니다.

내 예제 입력은 다음과 같습니다.

a   b   c
d   b   a

확장 출력은

intermediate output

a   b   c
c   b   c
d   b   c
a   y   c
c   y   c
d   y   c
a   b   m
c   b   m
d   b   m
a   y   m
c   y   m
d   y   m
a   b   n
c   b   n
d   b   n
a   y   n
c   y   n
d   y   n
d   b   a
p   b   a
d   y   a
p   y   a
d   b   c
p   b   c
d   y   c
p   y   c
d   b   d
p   b   d
d   y   d
p   y   d

그런 다음 이는 최종 출력을 얻기 위해 유효한 목록의 하위 집합으로 사용됩니다.

a   b   c
c   b   c
p   b   d
d   y   d
p   y   d

두 단계에 대한 작업 코드가 있습니다

awk '
    NR==FNR { 
        if ($3 > 0.7) {
            scr[$1,$2]=$3
            var[$1]
        } 
        next
    }
    { 
        for (col1 in var) {
            for (col2 in var) {
                for (col3 in var)    {
                    if ( 
                        scr[$1,col1] && scr[$2,col2] && scr[$3,col3] &&
                        scr[$1,col1] > 0.7   &&  
                        scr[$2,col2] > 0.7   && 
                        scr[$3,col3] > 0.7   && 
                        scr[$1,col1] + scr[$1,col1] > 1.6
                    ) {
                        print col1,  col2,   col3 
                    }
                }
            }
        }
    }
'  score input > intermediateout


grep -f intermediateout validlist > finalout

문제는 점수 파일에 3억 4500만 개의 레코드가 있고 유효한 목록에는 2600개의 레코드만 있다는 것입니다. 따라서 이 3개의 for 루프는 영원히 실행됩니다. 이 프로세스의 속도를 높이는 데 도움을 주실 수 있나요? 잘못된 조합을 먼저 필터링할 수 있으면 출력이 훨씬 작아지기 때문입니다.

이것은 내가 액세스할 수 있는 클러스터 메모리와 OS입니다.

 free -m
             total       used       free     shared    buffers     cached
Mem:        387591     299120      88471          2        481     292698


cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.6

당신의 도움을 주셔서 대단히 감사합니다! !

안녕하세요 Glenn, 서버에서 구문 오류가 발생했습니다. 좀 봐주시겠어요? 이상하게도 이 구문 오류는 cygwin에 표시되지 않습니다.

awk: cmd. line:9:         if ($3 > 0.7) clos[$1][$2]  # I would name this array "close"
awk: cmd. line:9:                               ^ syntax error
awk: cmd. line:15:             col[i][$i]
awk: cmd. line:15:                   ^ syntax error
awk: cmd. line:16:             for (key in clos[$i])
awk: cmd. line:16:                             ^ syntax error
awk: cmd. line:17:                 col[i][key]
awk: cmd. line:17:                       ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                              ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                   ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                  ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                       ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                                      ^ syntax error
awk: cmd. line:24:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:24:                                                                           ^ syntax error
awk: cmd. line:25:             if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) )
awk: cmd. line:25:                                                                             ^ unexpected newline or end of string
#

고쳐 쓰다:

안녕하세요 글렌,

gawk 4.xxx를 다운로드했는데 이 오류가 사라졌습니다. 제안해 주셔서 감사합니다.

코드를 꽤 많이 연구했는데 이제 2D 배열에 대해 더 잘 이해하게 된 것 같습니다. 감사합니다.

당면한 질문에 대해 제가 올바르게 이해했다면 근본적인 문제가 있습니다. 즉, 각 입력 행은 다른 행과 독립적으로 처리되어야 합니다. 따라서 각 입력 라인에는 가능한 출력 라인 세트가 있어야 합니다.

친밀감은 여기서 비롯됩니다.

각 입력 행에 대해 1) $1의 확장 변수는 $1의 0.7에 가까워야 합니다. 2) $2의 확장변수는 $2의 0.7에 가까워야 합니다. 3) $1 배열의 각 변수에 대해 $2 배열의 각 요소에 대해 closeless($1 및 $1 배열의 변수) + closeless($2 및 $2 배열의 변수)는 1.6보다 커야 합니다. 4) $3을 포함하는 확장 변수 종가 3달러는 0.7이어야 합니다.

3개의 입력 열을 기반으로 3개의 배열을 생성하면 "행당" 정보가 손실되고 압축 합계를 얻을 수 없습니다. 이것이 의미가 있는지 알려주십시오.

가능한 조정을 시도했지만 2차원 배열의 복잡성과 3차원 배열 사용 가능성에 빠져 있는 것 같습니다.

gawk '
    # validlist
    FILENAME == ARGV[1] {
        valid[$1 FS $2 FS $3]
        next
    }
    # scorefile
    FILENAME == ARGV[2] {
        if ($3 > 0.7) clos[$1][$2]
        scr[$1][$2]=$3;                   # I would name this array "close"
        next                        # but that is a keyword
    }
    # input
    {   

        col[NR FS $2][$1];
        col[NR FS $2][$2];
        col[NR FS $3][$3];

        for (key in clos[$i])
        {
            col[NR FS $1][$i];
            col[NR FS $2][$i];
            col[NR FS $3][$i];

            if scr[$1][i] + scr[$2][i] > 1.6
              possible[$i]=$1 FS $2 FS $3
        }


    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v in valid) {
           for (allposs in possible)
              if ( v==allpos  ) 
                print v
        }
    }
' validlist scorefile input

답변1

알겠습니다. 여기 있습니다. 핵심은 awk 프로그램이 유효한 목록도 읽도록 하는 것입니다. 점수 및 입력 파일을 처리합니다. 그런 다음 모든 순열이 아닌 유효한 조합을 반복합니다.

배열의 배열에 GNU awk 사용

gawk '
    # validlist
    FILENAME == ARGV[1] {
        valid[$1 FS $2 FS $3]
        next
    }
    # scorefile
    FILENAME == ARGV[2] {
        if ($3 > 0.7) clos[$1][$2]  # I would name this array "close"
        next                        # but that is a keyword
    }
    # input
    {
        for (i=1; i<=3; i++) {
            col[i][$i]
            for (key in clos[$i])
                col[i][key]
        }
    }
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v in valid) {
            split(v, a)
            if ( (a[1] in col[1]) && (a[2] in col[2]) && (a[3] in col[3]) ) 
                print v
        }
    }
' validlist scorefile input

산출

a b c
c b c
d y d
p b d
p y d

관련 정보