Как эффективно читать большие матрицы из CSV в Октаве - PullRequest
5 голосов
/ 26 сентября 2011

Есть много сообщений о медленной работе Octave dlmread.Я надеялся, что это было исправлено в 3.2.4, но когда я попытался загрузить файл CSV, который имеет размер около.8 * 4 мил (всего 32 мил), это также заняло очень много времени.Я искал в Интернете, но не мог найти обходной путь для этого.Кто-нибудь знает хороший обходной путь?

Ответы [ 3 ]

3 голосов
/ 01 ноября 2011

Я столкнулся с той же проблемой, и мне пригодился R, поэтому я решил использовать «read.csv» в R, а затем использовать пакет R «R.matlab», чтобы написать файл «.mat», и затем загрузить что в октаве.

"read.csv" также может быть довольно медленным, но в моем случае это работало очень хорошо.

2 голосов
/ 22 февраля 2012

Причина в том, что в Octave есть ошибка, заключающаяся в том, что добавление данных в очень большую матрицу занимает больше времени, чем добавление того же количества данных в небольшую матрицу.

Ниже моя попытка. Я предпочитаю сохранять данные каждые 50000 строк, поэтому я уже могу посмотреть, вместо того чтобы ждать. Это медленнее для небольших файлов, но гораздо быстрее для больших файлов.

function alldata = load_data(filename)
    fid = fopen(filename,'r');
    s=0;
    data=[];
    alldata=[];
    save "temp.mat" alldata;
    if fid == -1
        disp("Couldn't find file mydata");
    else
        while (~feof(fid))
            line = fgetl(fid);
            [t1,t2,t3,t4,d] = sscanf(line,'%i:%i:%i:%i %f', "C"); #reading time as hh:mm:ss:ms and data as float
            s++;
            t = (t1 * 3600000 + t2 * 60000 + t3 * 1000 + t4);
            data = [data; t, d];
            if (mod(s,10000) == 0)
                #disp(s), disp("  "), disp(t), disp("  "), disp(d), disp("\n");
                disp(s);
                fflush(stdout);
            end
            if (mod(s,50000) == 0)
                load "temp.mat";
                alldata=[alldata; data];
                data=[];
                save "temp.mat" alldata;
                disp("data saved");
                fflush(stdout);
            end
        end
        disp(s);
        load "temp.mat";
        alldata=[alldata; data];
        save "temp.mat" alldata;
        disp("data saved");
        fflush(stdout); 
    end
    fclose(fid);
1 голос
/ 30 июля 2015

Вот обходной путь, который я использую.

Я не обнаружил, что sscanf будет анализировать входные строки, как указано выше. Кроме того, я не использовал временный файл.

Мой файл .csv содержит большое количество строк. Они начинаются с заголовка из 18 строк и сопровождаются блоком данных, каждый из которых имеет 135 столбцов. Следующий код был протестирован. Мой файл также начинается с каждой строки с полем дд / мм / гггг чч: мм. Это также поймает плохие строки и покажет, где они находятся, используя try / catch.

Мой файл .csv был получен от клиента, который сбросил загрузку PARCView в файл Excel.

function [tags,descr,alldata] = fbcsvread(filename)
  fid = fopen(filename,'r');
  s = 0;
  data=[];
  alldata=zeros(1,135);
  if fid==-1
    disp("Couldn't find file %s\n",filename);
  else
    linecount = 1;
    while (~feof(fid))
      line = fgetl(fid);
      data2 = zeros(1,135);
      if linecount == 1
    tags = strsplit(line,",");
      elseif linecount == 2
    descr = strsplit(line,",");
      elseif linecount >= 19
    data = strsplit(line,",");
    datetime = strsplit(char(data(1))," ");
    modyyr = strsplit(char(datetime(1)),"/");
    hrmin = strsplit(char(datetime(2)),":");
    year1 = sscanf(char(modyyr(3)),"%d","C");
    day1 = sscanf(char(modyyr(2)),"%d","C");
    month1 = sscanf(char(modyyr(1)),"%d","C");
    hour1 = sscanf(char(hrmin(1)),"%d","C");
    minute1 = sscanf(char(hrmin(2)),"%d","C");
    realtime = datenum(year1,month1,day1,hour1,minute1);
    data2(1) = realtime;
    for location = 2:134
      try
        data2(location) = sscanf(char(data(location)),"%f","C");
      catch
        printf("Error at %s %s\n",char(datetime(1)),char(datetime(2)) );
        fflush(stdout);
      end_try_catch
    endfor
    alldata(linecount-18,:) = data2;
    if mod(linecount,50) == 0
      printf(".");
      fflush(stdout);
    endif
      endif
      linecount = linecount + 1;
    endwhile
    fclose(fid);
  endif
endfunction
...