我正在试图修复大量具有许多重叠列的csv文件。
library(plyr)
filenames <- list.files("output/", pattern = "*.csv")
filenames = paste("output/", filenames, sep="")
frames = lapply(filenames,read.csv,header=TRUE)
input = do.call(rbind.fill,frames)
write.csv(input, file="stacked.csv", quote=FALSE, na="", row.names=FALSE)
组合框架将有大约300,000行,并且列的并集为3,000左右,并且有104个文件。这样做我的电脑超过其内存限制(32gb),R崩溃。我也尝试将进程拆分为处理分段内存。再一次,没有运气:
library(plyr)
filenames <- list.files("output/", pattern = "*.csv")
filenames = paste("output/", filenames, sep="")
input = lapply(filenames,read.csv,header=TRUE)
part1 = do.call(rbind.fill,input[1:30])
save(part1,part2,file="p1")
part2 = do.call(rbind.fill,input[31:70])
part3 = do.call(rbind.fill,input[71:104])
write.table(input, file="stacked.csv", quote=FALSE, na="", row.names=FALSE)
以上只是我所做的一个例子。一旦我将part1,part2,part3加载回内存,它们总共约为6gb。在保存和加载之前,我的内存使用量约为20GB。然后我再次尝试rbind.fill(part1,part2)
并且内存使用率高峰> 32gb。
有关如何处理此问题的任何建议?我对其他解决方案(python,sql等)持开放态度。
答案 0 :(得分:1)
使用内存非常低但磁盘的算法是:
NA
添加到缺失的列中,并将该行写入一个大文件。只有当你完成后,你才能将那个大文件读入你的R会话(如果它不是太大。)
其他语言可能更适合此类任务。想到Perl。
编辑:如果您有兴趣,这是使用Perl的代码。将其放在rbindfill.pl
文件中,然后运行如下:perl rindfill.pl > output.csv
use strict;
use warnings;
my @files = glob "output/*.csv";
my %fields;
foreach my $file (@files)
{
open my $fh, '<', $file;
my $header = <$fh>;
chomp $header;
map {$fields{$_} = 1} split ',', $header;
close $fh;
}
my @all_fields = keys %fields;
print join(',', @all_fields) . "\n";
foreach my $file (@files)
{
open my $fh, '<', $file;
my $header = <$fh>;
chomp $header;
my @fields = split ',', $header;
foreach my $line (<$fh>)
{
chomp $line;
my $rec;
@{$rec}{@fields} = split ',', $line;
print join(',', map { defined $rec->{$_} ? $rec->{$_} : ''} @all_fields) . "\n";
}
close $fh;
}
答案 1 :(得分:1)
这是我使用的python代码。它还为文件名添加了一列,删除了无法转换为浮点数的任何内容(特别是文本字段),并在写入输出文件时跳过一行(包括标题的两行)。
import csv
import glob
files = glob.glob("data/*.txt")
csv.field_size_limit(1000000000)
outfile = "output.csv"
def clean_row(row,filename):
for k,v in row.items():
try:
row[k] = float(v)
except:
row[k] = ""
row['yearqtr'] = filename
return row
headers = set()
for filename in files:
with open(filename,"r") as infile:
reader = csv.reader(infile)
for header in next(reader):
headers.add(header)
headers = list(headers)
headers.insert(0,"yearqtr")
with open(outfile, "w") as outfile:
writer = csv.DictWriter(outfile,headers,restval="",extrasaction="ignore")
writer.writeheader()
for filename in files:
with open(filename, "r") as infile:
reader = csv.DictReader(infile)
next(reader)
writer.writerows((clean_row(row,filename) for row in reader))