먼저 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