我有一个包含值和频率的文件。我使用以下命令awk {a [$ 1] + = $ 2} END 添加具有相同值的列的频率。但是,该文件包含3GB的数据,我需要一个内存有效的解决方案。所以我首先对文件进行了排序,并尝试添加连续的列,如果它们相同,但我没有这样做,
答案 0 :(得分:1)
如果您先排序数据并在之后处理,那该怎么办:
$ cat > assumed_data.txt
VALUE1 1
VALUE2 2
VALUE1 3
VALUE2 4
$ sort assumed_data.txt|awk 'NR>1 && prev != $1 {print prev, sum; sum=0} {sum+=$2; prev=$1} END {print prev, sum}'
VALUE1 4
VALUE2 6
答案 1 :(得分:0)
...或计数并分批打印出来,例如处理1000行并将它们打印到另一个文件,接下来的1000行并附加到同一个文件中:
$ cat divisum.awk
NR % 1000 ==0 {
for(i in sum)
print i, sum[i]
delete sum
}
{
sum[$1]+=$2
}
END {
for(i in sum)
print i, sum[i]
}
$ awk -f divisum.awk assumed_data.txt > summedsome.txt
然后:
$ awk -f divisum.awk summedsome.txt > summedsomore.txt
......等等。不知道你所有1000的数据可能是也可能不是很多行。如果您的文件正好均匀分布了1000个不同的值,则一次1000行不能解决您的问题。
答案 2 :(得分:0)
如果您确实遇到了内存问题,因为您可以在文件上运行sort
,我不相信您这样做了,那么您需要这样的内容来解决它:
awk '
!full {
if ( ($1 > prevMax) || (NR == FNR) ) {
sum[$1] += $2
if ( length(sum) == 1000000 ) {
full = 1
for ( i in sum ) {
min = ( $1<min ? $1 : min)
max = ( $1>max ? $1 : max)
}
}
}
next
}
($1 >= min) && ($1 =< max) {
sum[$1] += $2
}
ENDFILE {
if ( length(sum) > 0 ) {
for ( i in sum ) {
print i, sum[i]
}
ARGV[ARGC] = FILENAME
ARGC++
delete sum
full = 0
prevMax = max
}
}
' file
检查数学/逻辑,但希望您能够一次计算最多1000000个唯一值,并继续将输入文件添加回ARGV列表,直到不再有唯一值。按摩1000000以适应。
以上使用GNU awk作为ENDFILE,其他awks你必须使用文件中的行数或使用FNR == 1和退出或类似。
答案 3 :(得分:0)
您经常可以将RAM换成磁盘,因此请通过文件一次性将其按值分成文件 - 因此所有VALUE1
个频率都会放入文件f.VALUE1
和所有VALUE2
个频率进入档案f.VALUE2
。
awk '{print $2 > "f." $1}' yourFile
然后,你需要总计每个f.*
中的数字。此解决方案一次只能在内存中保存一行: - )
答案 4 :(得分:0)
另一种解决方法是使用 GNU Parallel 。它可以将文件分块为任意大小的块,并为您并行处理它们。它只会分成整行 - 除非你做其他我不建议的东西,所以不存在分裂的风险。
因此,假设我在awk
中使用您的script.awk
脚本,如下所示:
{a[$1]+=$2}
END{for(i in a)print i,a[i]}
并假设您的文件名为data
,我可以将 GNU Parallel 块文件分成10MB块并将它们与CPU并行传递给尽可能多的awk
有核心:
parallel -a data --pipepart --block 10m awk -f ./script.awk
现在只要在任何10MB块中有重复值,这将减少您的数据。你可以明显地使块更大并且它将会有更大的减少,因为你将有更好的参考局部性,你也可以通过改变块大小来测试你的缺乏记忆的理论。您也可以反复应用上述内容,直到文件大小小于内存,这意味着您可以将内存全部放入内存中。我的意思是:
parallel -a data --pipepart --block 10m awk -f ./script.awk > part1
parallel -a part1 --pipepart --block 10m awk -f ./script.awk > part2
正如Ed所说,问题是您拥有多少唯一值,而不是您有多少值。您拥有的唯一值越少,它们在文件中的距离越近,此方法收敛的速度就越快。