2013-02-12 3 views
2

У меня есть несколько файлов CSVкот из двух структуры: не одни и те же поля

a.csv

field_a, field_b 
111,  121 
112,  122 

b.csv

field_a, field_c 
211,  231 
212,  232 

c.csv

field_a, field_b, field_c 
311,  321,  331 
312,  322,  332 

И я хотел бы объединить их

output.csv

field_a,field_b,field_c 
111, 121, NA 
112, 122, NA 
211, NA,  231 
212, NA,  232 
311, 321, 331 
312, 322, 332 

Я хотел бы сделать это с октаву.

Что я сделал до сих пор:

a=csv2cell(a.csv) 
A=cell2struct(a(2:end,:),a(1,:),1) 

и теперь я ищу что-то вроде

слияния (A, B, C) или vertcat (A, B, C)

но я не понял, что все поля находятся на выходе.

Whith R я сделал это так:

filelist<-list.files() 
for (i in 1:length(filelist)) { 
    datas[[i]]<-list(as.data.frame(read.csv(filelist[i]))) 
    merged <- merge(merged,datas[[i]], all=TRUE)} 

но для петли страшно медленно. Поэтому я ищу возможность объединить их все сразу.

+2

Неэффективное R код часто медленно. Это не операция слияния. Это операция укладки. –

+0

Да, я не знал лучшего способа. У Аруна была лучшая идея. – telemachos

ответ

0

Как я сделал я, наконец:

С Октава (MATLAB)

% FileNames=readdir(pwd); 
d=dir(pwd); 

isDirIdx = [d.isdir]; 
names = {d.name}; 
FileNames = names(~isDirIdx); 

for ii = 1:numel(FileNames) 
    % Load csv to cell 
    datas{ii}=csv2cell(FileNames{ii}); 
    % Then I convert them to a struct 
    Datas{ii}=cell2struct((datas{ii}(2:end,:)),[datas{ii}(1,:)],2); 
    try fields=[fields, fieldnames(Datas{ii})'];% fails for the first loop, becauce 'fields' doesn't exist yet 
    catch 
    fields=[fieldnames(Datas{ii})']; % create 'fields' in the first loop 
    end 
    Datalenght(ii)=numel(Datas{ii}(1)); 
end 

cd(startdir) 

for jj=1:numel(Datas) 
    missing_fields{jj} = setdiff(fields,fieldnames(Datas{jj})); 
    for kk=1:numel(missing_fields{jj}) 
    [Datas{jj}.(missing_fields{jj}{kk})]=deal(NaN);%*zeros(numel(datas{jj}(2:end,1)),1);) 
    end 
end 

Проблема была, я не видел, как легко способ экспорта структуры в csv. Поэтому я переключаюсь обратно на R. Поскольку у меня недостаточно памяти, я не мог загрузить все файлы в r и экспортировать их как один csv. Поэтому сначала я экспортировал каждый файл netcdf в csv с точно такими же значениями. Затем я объединил их всех с командой unix/gnu cat.

R:

# Converts all NetCDF (*.nc) in a folder to ASCII (csv) 
# when there are more then one, all csv will have the same fields 
# when there is a field missing in one NetCDF file, this scripts adds 'NA' Values 

# it saves memory, because there is always only one NetCDF-File in the memory. 

# Needs package RNetCDF: 
# http://cran.r-project.org/web/packages/RNetCDF/index.html 
# load package 
library('RNetCDF') 

# get list of all files to merge 
filelist<-list.files() 

# initialise variable names 
varnames_all<-{} 
varnames_file<-list(filelist) 

n_files<-length(filelist) 
n_vars<-rep(NA,n_files) # initialise 

# get variables-names of each NetCDF file 
for (i in 1:n_files) { 
    ncfile<-open.nc(filelist[i]) # open nc file 
    print(paste(filelist[i],"opend!")) 

    # get number of variable in the NetCDF 
    n_vars[i]<-file.inq.nc(ncfile)$nvars 
    varnames="" # initialise and clear 

    # read every variable name 
    for (j in 0:(n_vars[i]-1)) { 
    varnames[j]<-var.inq.nc(ncfile,j)$name 
    } 
    close.nc(ncfile) 
    varnames_file[[i]]<-varnames # add to the list of all files 
    varnames_all<-(c(varnames_all,varnames)) # concat to one array 
} 

varnames_all<-unique(varnames_all) # take every varname only once 
print("Existing variable names:") 
print(varnames_all) 

#initialise a data.frame for load the NetCDF 
datas<-data.frame() 

for (i in 1:length(filelist)) { 
    print(filelist[i]) 
    ncfile<-open.nc(filelist[i]) # open nc file 
    print(paste("reading ", filelist[i], "...")) 
    datas<-as.data.frame(read.nc(ncfile)) #import data from ncfile as data frame 
    close.nc(ncfile) 

    #check witch variables are missing 
    missing_vars<-setdiff(varnames_all,colnames(datas)) 

    # Add missing variables a colums with NA 
    datas[missing_vars]<-NA 
    print(paste("writing ", filelist[i], " to ", filelist[i],".csv ...", sep="")) 

    #reorder colum in the same way as in the array varname_all 
    datas<-datas[varnames_all] 

    # Write File 
    write.csv(datas,file=paste(filelist[i],".csv", sep="")) 

    # clear Memory 
    rm(datas) 
} 

Тогда кошка прямо вперед

#!/bin/bash 
# Concatenate csv files, whitch have exactly the same fields 

## Change to the directory, from where the files is executed 
path=$PWD 
cd $path 

if [ $# -gt 0 ]; then 
    cd $1 
fi 

# get a list of all data files 
datafile_list=$(ls) 
read -a datafile_array <<< $datafile_list 
echo "copying files ..." 
echo "copying file:" ${datafile_array[0]} 

cat < ./${datafile_array[0]} > ../outputCat.csv 
for ((i=1; i<${#datafile_array[@]}; i++)) 
    do 
    echo "copying file" ${datafile_array[$i]} 
    cat < ./${datafile_array[$i]} | tail -n+2 >> ../outputCat.csv 
done 
4

rbind.fill из plyr пакета должен справиться с этим прекрасно:

require(plyr) 
rbind.fill(a,b,c) 

# field_a field_b field_c 
# 1  111  121  NA 
# 2  112  122  NA 
# 3  211  NA  231 
# 4  212  NA  232 
# 5  311  321  331 
# 6  312  322  332 
+0

Я думаю, что это работает в целом, но у меня проблемы с моим размером memoery, и это приводит к ошибке. Я должен искать лучшую машину ... – telemachos

+1

Каков размер ваших данных? И какая у тебя память? И вы используете 32-битную версию R? (используйте 'sessionInfo()', чтобы узнать последнюю часть) – Arun

+1

Если проблемы с памятью являются проблемой, тогда вам следует подумать об использовании базы данных и доступе к данным из пакета sqldf. –

1

Я не уверен, что октава - но в Matlab я бы использовать fieldnames и набор функций.

В псевдокода что-то вроде этого:

all_fields = union of fieldnames(a), fieldnames(b) and fieldnames(c) 
for each variable: 
    missing_fields = setdiff(all_fields,fieldnames) 
    add the missing fields 
then join 
+0

Хорошо, я думаю, что это тоже может быть хорошим способом получить один и тот же блок-конструктор, но не конкатенировать их (из-за размера памяти). – telemachos

+0

Но это приводит к некоторым другим вопросам: [установка нескольких полей одновременно] (http://stackoverflow.com/q/14870828/1842684) – telemachos

Смежные вопросы