Как мне прочитать файл с разделителями со строками / числами в Octave? - PullRequest
20 голосов
/ 14 марта 2011

Я пытаюсь прочитать текстовый файл, содержащий цифры и строки, используя Octave. Формат файла примерно такой:

A B C
10 100
б 20 200
с 30 300
д 40 400
E 50 500

но разделителем может быть пробел, табуляция, запятая или точка с запятой. Функция textread отлично работает, если в качестве разделителя используется пробел / табуляция:

[A,B,C] = textread ('test.dat','%s %d %d','headerlines',1)

Однако это не работает, если разделитель - запятая / точка с запятой. Я пытался использовать dklmread:

dlmread ('test.dat',';',1,0)

но это не работает, потому что первый столбец является строкой. По сути, с textread я не могу указать разделитель, а с dlmread я не могу указать формат первого столбца. По крайней мере, не с версиями этих функций в Octave. У кого-нибудь была такая проблема раньше?

Ответы [ 2 ]

13 голосов
/ 12 июня 2012

textread позволяет указать разделитель - он учитывает аргументы свойства strread. У меня работал следующий код:

[A,B,C] = textread( 'test.dat', '%s %d %d' ,'delimiter' , ',' ,1 )
6 голосов
/ 30 ноября 2011

Я не мог найти простой способ сделать это в Октаве в настоящее время. Вы можете использовать fopen() для циклического перемещения по файлу и извлечения данных вручную. Я написал функцию, которая будет делать это на произвольных данных:

function varargout = coltextread(fname, delim)

    % Initialize the variable output argument
    varargout = cell(nargout, 1);

    % Initialize elements of the cell array to nested cell arrays
    % This syntax is due to {:} producing a comma-separated 
    [varargout{:}] = deal(cell());

    fid = fopen(fname, 'r');

    while true
        % Get the current line
        ln = fgetl(fid);

        % Stop if EOF
        if ln == -1
            break;
        endif

        % Split the line string into components and parse numbers
        elems = strsplit(ln, delim);
        nums = str2double(elems);

        nans = isnan(nums);

        % Special case of all strings (header line)
        if all(nans)
            continue;
        endif

        % Find the indices of the NaNs 
        % (i.e. the indices of the strings in the original data)
        idxnans = find(nans);

        % Assign each corresponding element in the current line
        % into the corresponding cell array of varargout
        for i = 1:nargout
            % Detect if the current index is a string or a num
            if any(ismember(idxnans, i))
                varargout{i}{end+1} = elems{i};
            else
                varargout{i}{end+1} = nums(i);
            endif
        endfor
    endwhile

endfunction

Он принимает два аргумента: имя файла и разделитель. Функция определяется количеством указанных возвращаемых переменных, поэтому, например, [A B C] = coltextread('data.txt', ';'); будет пытаться проанализировать три разных элемента данных из каждой строки в файле, в то время как A = coltextread('data.txt', ';'); будет анализировать только первые элементы. Если возвращаемая переменная не указана, функция не будет ничего возвращать.

Функция игнорирует строки, содержащие все строки (например, заголовок «A B C»). Просто удалите раздел if all(nans)..., если хотите все.

По умолчанию 'столбцы' возвращаются как массивы ячеек, хотя числа в этих массивах фактически являются преобразованными числами, а не строками. Если вы знаете, что массив ячеек содержит только числа, вы можете легко преобразовать его в вектор-столбец с помощью: cell2mat(A)'.

...