内存有效转置-Awk

内存有效转置-Awk,awk,transpose,Awk,Transpose,我正在尝试使用以下脚本转置一个表(10k行X 10k列) 一个简单的数据示例 $cat rm1 t1 t2 t3 n1 1 2 3 n2 2 3 44 n3 1 1 1 $sh transpose.sh rm1 n1 n2 n3 t1 1 2 1 t2 2 3

我正在尝试使用以下脚本转置一个表(10k行X 10k列)

一个简单的数据示例

$cat rm1

        t1      t2      t3
n1      1       2       3
n2      2       3       44
n3      1       1       1
$sh transpose.sh rm1

        n1      n2      n3
t1      1       2       1
t2      2       3       1
t3      3       44      1
然而,我得到了内存错误。任何帮助都将不胜感激

awk -F "\t" '{
for (f = 1; f <= NF; f++)
a[NR, f] = $f
}
NF > nf { nf = NF }
END {
for (f = 1; f <= nf; f++)
for (r = 1; r <= NR; r++)
printf a[r, f] (r==NR ? RS : FS)
}'

正如我在评论中提到的,这里有一种方法可以分块完成。在这里,我展示了一个很小的
12r x 10c
文件的机制,但在不到一分钟的时间内,我还在
10K x 10K
文件上运行了1000行

<>强>编辑< /强>下面更新,以考虑行数和列数不相等的<代码> m x n< /COD>矩阵。以前的版本仅适用于“N x N”矩阵

$ cat et.awk
BEGIN {
    start = chunk_start
    limit = chunk_start + chunk_size - 1
}

{
    n = (limit > NF) ? NF : limit
    for (f = start; f <= n; f++) {
        a[NR, f] = $f
    }
}

END {
    n = (limit > NF) ? NF : limit

    for (f = start; f <= n; f++)
      for (r = 1; r <= NR; r++)
        printf a[r, f] (r==NR ? RS : FS)
}


$ cat t.txt
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29 
30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 
50 51 52 53 54 55 56 57 58 59 
60 61 62 63 64 65 66 67 68 69 
70 71 72 73 74 75 76 77 78 79 
80 81 82 83 84 85 86 87 88 89 
90 91 92 93 94 95 96 97 98 99 
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 


$ cat et.sh
inf=$1
outf=$2

rm -f $outf
for i in $(seq 1 2 12); do
    echo chunk for rows $i $(expr $i + 1)
    awk -v chunk_start=$i -v chunk_size=2 -f et.awk $inf >> $outf
done



$ sh et.sh t.txt t-transpose.txt
chunk for rows 1 2
chunk for rows 3 4
chunk for rows 5 6
chunk for rows 7 8
chunk for rows 9 10
chunk for rows 11 12


$ cat t-transpose.txt 
10 20 30 40 50 60 70 80 90 A0 B0 C0
11 21 31 41 51 61 71 81 91 A1 B1 C1
12 22 32 42 52 62 72 82 92 A2 B2 C2
13 23 33 43 53 63 73 83 93 A3 B3 C3
14 24 34 44 54 64 74 84 94 A4 B4 C4
15 25 35 45 55 65 75 85 95 A5 B5 C5
16 26 36 46 56 66 76 86 96 A6 B6 C6
17 27 37 47 57 67 77 87 97 A7 B7 C7
18 28 38 48 58 68 78 88 98 A8 B8 C8
19 29 39 49 59 69 79 89 99 A9 B9 C9

将下一个
chunk\u start
设置为1001等(当然,在输出中添加
),这样做十次,最终将得到完整的转置结果。

有一个基于排序的简单快速算法:

1) 通过输入,在每个字段前面加上行号和列号。输出是矩阵中每个单元格的行、列、值的三元组。将输出写入临时文件

2) 按列,然后按行对临时文件进行排序

3) 通过已排序的临时文件,重建转置矩阵

两个外部通道由awk完成。排序由系统排序完成。代码如下:

$ echo '1 2 3
2 3 44
1 1 1' |
awk '{ for (i=1; i<=NF; i++) print i, NR, $i}' |
sort -n |
awk ' NR>1 && $2==1 { print "" }; { printf "%s ", $3 }; END { print "" }'
1 2 1
2 3 1
3 44 1
$echo'1 2 3
2 3 44
1 1 1' |
awk'{for(i=1;i1&&$2==1{print”“};{printf”%s',$3};END{print”“}
1 2 1
2 3 1
3 44 1

好吧,一亿个字段将需要一些RAM来缓存。你能告诉我们一些关于数据文件的信息吗?例如,如果数据文件只包含数字,那么知道这些信息会很有用。除此之外:速度有多重要?可能是某种分块。缓存前100列并写入前100列ws.在下一个100中重复,等等。你可以尝试在没有内存错误的情况下它可以处理多大的块,并进行相应的设置。这是一个很好的问题,我很想看看人们想出了什么。在OSX/BSD上,你可以使用
rs-T
我刚刚意识到,如果行数是12k,列数是10k,输出只是打印10k将行转换为列。因此剩余的2000行丢失。希望我解释得很好…是的,我看到了问题!希望我今天晚些时候能为您提供更新。请参阅已编辑的awk脚本。有一个错误假设行数和列数相同。这个错误我无法重现。我对8556列和9192行进行了测试d另一个有那么多列和4096行(用于测试行数多于或少于列数的行)。两个测试都进行得很顺利。您如何调用awk脚本?您是对的。它工作正常。我只是运行方式错误。感谢再次检查。您真的很有帮助。
$ time awk -v chunk_start=1 -v chunk_size=1000 -f et.awk tenk.txt  > tenk-transpose.txt

real    1m7.899s
user    1m5.173s
sys     0m2.552s
$ echo '1 2 3
2 3 44
1 1 1' |
awk '{ for (i=1; i<=NF; i++) print i, NR, $i}' |
sort -n |
awk ' NR>1 && $2==1 { print "" }; { printf "%s ", $3 }; END { print "" }'
1 2 1
2 3 1
3 44 1