2012-05-14 2 views
3

У меня есть файл csv, который содержит 2d массивы из 4 столбцов, но различное количество строк. Например:Matlab, прочитайте несколько массивов 2d из файла csv

2, 354, 23, 101 
3, 1023, 43, 454 
1, 5463, 45, 7657 

4, 543, 543, 654 
3, 56, 7654, 344 

... 

Мне нужно, чтобы иметь возможность импортировать данные таким образом, что я могу запустить операции на каждом блоке данных, однако csvread, dlmread и TextScan все игнорируют пустые строки.

Я не могу найти решение в любом месте, как это можно сделать?

PS:

Может быть, стоит отметить, что файлы формата выше, на самом деле конкатенация многих файлов, содержащих только один блок данных (я не хочу, чтобы читать из тысяч файлы каждый раз), поэтому пустую строку между блоками можно изменить на любой другой разделитель/маркер. Это делается только с помощью скрипта python.

EDIT: Мое решение - основано на/вдохновленный Petrichor ниже

Я заменил csvread с TextScan, который быстрее. Тогда я понял, что, если я заменил пустые строки линиями nan вместо (изменяя мой скрипт python), я мог бы удалить необходимость в секундомерном textscan медленной точке. Мой код:

filename = 'data.csv'; 
fid = fopen(filename); 
allData = cell2mat(textscan(fid,'%f %f %f %f','delimiter',',')); 
fclose(fid); 

nanLines = find(isnan(allData(:,1)))'; 

iEnd = (nanLines - (1:length(nanLines))); 
iStart = [1 (nanLines(1:end-1) - (0:length(nanLines)-2))]; 
nRows = iEnd - iStart + 1; 

allData(nanLines,:)=[]; 

data = mat2cell(allData, nRows); 

Оценка: 0.28s (Файл всего в 103000 линий). Я принял решение Petrichor, так как он действительно лучше решает мою первоначальную проблему.

+0

Я полагаю, один из способов было бы заменить пустые строки с чем-то вроде NaN, NaN, NaN, NaN, а затем после загрузки данных с использованием csvread или что-то подобное, вы могли бы прокручивать данные и извлекать блоки в Matlab довольно легко. – Dan

+0

Я надеялся избежать необходимости повторять данные после импорта, поскольку (я предполагаю) это просто добавит больше времени на весь процесс. В другом примечании, я нашел до сих пор, что textscan - самый быстрый способ импорта? –

+0

Как бы не оставить строку разделителя вообще, а создать второй файл, который является только индексом строк, когда начинаются новые блоки, а затем использовать этот файл, чтобы определить диапазон строк для работы, а не создавать отдельные матрицы для каждого? – Dan

ответ

1
filename = 'data.txt'; 

%# Read all the data 
allData = csvread(filename); 

%# Compute the empty line indices 
fid = fopen(filename); 
lines = textscan(fid, '%s', 'Delimiter', '\n'); 
fclose(fid); 
blankLines = find(cellfun('isempty', lines{1}))'; 

%# Find the indices to separate data into cells from the whole matrix 
iEnd = [blankLines - (1:length(blankLines)) size(allData,1)]; 
iStart = [1 (blankLines - (0:length(blankLines)-1))]; 
nRows = iEnd - iStart + 1; 

%# Put the data into cells 
data = mat2cell(allData, nRows) 

Это дает следующие Ваши данные:

data = 

    [3x4 double] 
    [2x4 double] 
+1

Спасибо petrichor, хорошее решение. Как я уже упоминал в своем комментарии выше, я надеялся избежать обратной связи с данными, но ваше решение обеспечивает хорошую среднюю позицию. Сроки по моим фактическим данным: я обнаружил, что csvread занимает 0,46 секунды, в то время как использование textscan занимает всего 0.26. Соответственно, ваше решение, когда я заменю csvread на textscan, занимает всего 0,49 секунды, что должно быть достаточно быстрым для меня. Мне все еще интересно, есть ли способ «одного шага», хотя ... Большое спасибо –

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