читать CSV-файл в Matlab со строками разного размера - PullRequest
1 голос
/ 12 мая 2019

Я собираюсь прочитать большой файл CSV в Matlab, который содержит такие строки:

1, 0, 1, 0, 1
1, 0, 1, 0, 1, 0, 1, 0, 1
1, 0, 1
1, 0, 1
1, 0, 1, 0, 1
0, 1, 0, 1, 0, 1, 0, 1, 0

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

Использование csvread помогает, но это слишком медленно и кажется неэффективным.Есть ли способы использовать textscan с неизвестным количеством входов в каждой строке?или у вас есть другие предложения для этой ситуации?

1 Ответ

2 голосов
/ 13 мая 2019

Поскольку вы сказали " Числовая матрица с нулями была бы хороша ", существует решение, использующее textscan, которое может дать вам это. Однако выгода заключается в том, что вы должны знать максимальное количество элементов, которое может иметь строка (т. Е. Самая длинная строка в вашем файле).

Если вы знаете, что комбинация дополнительных параметров для textscan позволит вам прочитать неполную строку:

Если вы установите параметр 'EndOfLine','\r\n', документация поясняет:

Если отсутствуют пропущенные значения и последовательность конца строки в конце последняя строка в файле, тогда текст может вернуть пустые значения для тех поля. Это гарантирует, что отдельные ячейки в выходном массиве ячеек, C, одинакового размера.

Итак, данные примера в вашем вопросе сохранены как differentRows.txt, следующий код:

% be sure about this, better to overestimate than underestimate
maxNumberOfElementPerLine = 10 ;

% build a reading format which can accomodate the longest line
readFormat = repmat('%f',1,maxNumberOfElementPerLine) ;

fidcsv = fopen('differentRows.txt','r') ;

M = textscan( fidcsv , readFormat , Inf ,...
    'delimiter',',',...
    'EndOfLine','\r\n',...
    'CollectOutput',true) ;

fclose(fidcsv) ;
M = cell2mat(M) ; % convert to numerical matrix

вернет:

>> M
M =
     1     0     1     0     1   NaN   NaN   NaN   NaN   NaN
     1     0     1     0     1     0     1     0     1   NaN
     1     0     1   NaN   NaN   NaN   NaN   NaN   NaN   NaN
     1     0     1   NaN   NaN   NaN   NaN   NaN   NaN   NaN
     1     0     1     0     1   NaN   NaN   NaN   NaN   NaN
     0     1     0     1     0     1     0     1     0   NaN

В качестве альтернативы, если это приводит к значительной разнице в скорости, вы можете импортировать данные в целые числа вместо двойных. Проблема в том, что NaN не определено для целых чисел, поэтому у вас есть 2 варианта:

  • 1) Оставьте записи пусто по умолчанию 0

просто замените строку, определяющую спецификатор формата:

% build a reading format which can accomodate the longest line
readFormat = repmat('%d',1,maxNumberOfElementPerLine) ;

Это вернет:

>> M
M =
1   0   1   0   1   0   0   0   0   0
1   0   1   0   1   0   1   0   1   0
1   0   1   0   0   0   0   0   0   0
1   0   1   0   0   0   0   0   0   0
1   0   1   0   1   0   0   0   0   0
0   1   0   1   0   1   0   1   0   0

  • 2) Заменить пустые записи на заполнители (например: 99)

Определите значение, которое, как вы уверены, никогда не будет в исходных данных (для быстрой идентификации пустых ячеек), затем используйте параметр EmptyValue функции textscan:

readFormat = repmat('%d',1,maxNumberOfElementPerLine) ;
DefaultEmptyValue = 99 ; % placeholder for "empty values"

fidcsv = fopen('differentRows.txt','r') ;
M = textscan( fidcsv , readFormat , Inf ,...
    'delimiter',',',...
    'EndOfLine','\r\n',...
    'CollectOutput',true,...
    'EmptyValue',DefaultEmptyValue) ;

даст:

>> M
M =
1   0   1   0   1   99  99  99  99  99
1   0   1   0   1   0   1   0   1   99
1   0   1   99  99  99  99  99  99  99
1   0   1   99  99  99  99  99  99  99
1   0   1   0   1   99  99  99  99  99
0   1   0   1   0   1   0   1   0   99
...