Прочтите текстовый файл и разделите данные на разные столбцы и разные таблицы в MATLAB

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

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

Вот как выглядит документ:

    time    V(A,B)  I(R1)
    Step Information: X=1  (Run: 1/11)
    0.000000000000000e+000  -2.680148e-016  0.000000e+00
    9.843925313007988e-012  -4.753470e-006  2.216314e-011
    1.000052605772457e-011  -4.835427e-006  2.552497e-011
    1.031372754715773e-011  -4.999340e-006  -3.042096e-012
    1.094013052602406e-011  -5.327165e-006  -1.206968e-011
    Step Information: X=1  (Run: 2/11)
    0.000000000000000e+000  -2.680148e-016  0.000000e+000
    9.843925313007988e-012  -4.753470e-006  2.216314e-011
    1.000052605772457e-011  -4.835427e-006  2.552497e-011
    1.031372754715773e-011  -4.999340e-006  -3.042096e-012
    1.094013052602406e-011  -5.327165e-006  -1.206968e-011

person user256247    schedule 28.01.2016    source источник
comment
Самое простое решение - использовать отдельные вызовы textscan для ваших числовых и текстовых данных.   -  person Daniel    schedule 28.01.2016
comment
Постоянно ли количество шагов на цикл?   -  person excaza    schedule 28.01.2016


Ответы (2)


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

Примерно так будет работать, если файл хранится в 'file.txt':

%// Open the file
f = fopen('file.txt', 'r');

%// Initialize empty cell array
data = {};

%// Initialize temporary matrix
temp = [];

%// Loop over the file...
while true
    %// Get a line from the file
    line = fgetl(f);

    %// If we reach the end of the file, get out
    if line == -1
        %// Last check before we break
        %// Check if the temporary matrix isn't empty and add
        if ~isempty(temp)
            data = [data; temp];
        end
        break; 
    end

    %// Else, check to see if this line contains three numbers
    numbers = textscan(line, '%f %f %f');

    %// If this line doesn't consist of three numbers...
    if all(cellfun(@isempty, numbers))
        %// If the temporary matrix is empty, skip
        if isempty(temp)
            continue;
        end
        %// Concatenate to cell array
        data = [data; temp];
        %// Reset temporary matrix
        temp = [];
    %// If this does, then create a row vector and concatenate
    else
        temp = [temp; numbers{:}];
    end
end

%// Close the file
fclose(f);

Код довольно понятен, но давайте углубимся в него, чтобы убедиться, что вы знаете, что происходит. Сначала откройте файл с помощью fopen, чтобы получить "указатель" на файл, затем инициализируйте наш массив ячеек, который будет содержать наши матрицы, а также временную матрицу, используемую при чтении матриц между информацией заголовка. После того, как мы просто переберем каждую строку файла и сможем выделить строку с помощью fgetl < / a> используя созданный нами указатель файла. Затем мы проверяем, достигли ли мы конца файла, и если да, то давайте проверим, есть ли во временной матрице какие-либо числовые данные. Если это так, добавьте это в наш массив ячеек и, наконец, выйдите из цикла. Мы используем fclose, чтобы закрыть файл и очистить его.

Теперь суть операции - это то, что следует после этой проверки. Мы используем textscan и ищем три числа, разделенных пробелами. Это сделано с помощью спецификатора формата '%f %f %f'. Это должно дать вам массив ячеек из трех элементов, если вы добились успеха с числами. Если это верно, преобразуйте этот массив ячеек элементов в строку чисел и объедините ее во временную матрицу. Выполнение temp = [temp; numbers{:}]; облегчает эту конкатенацию. Просто соединяю каждое число вместе и соединяю их по горизонтали, чтобы создать одну строку чисел. Затем я беру эту строку и объединяю ее как другую строку во временной матрице.

Если мы наконец дойдем до строки, где весь текст, это даст вам все три элемента в массиве ячеек, найденных textscan, чтобы быть пустыми. Это цель all и _ 11_ позвонить. Мы ищем каждый элемент в ячейке и смотрим, пуст ли он. Если каждый элемент пуст, это строка текста. Если возникает такая ситуация, просто возьмите временную матрицу и добавьте ее как новую запись в свой массив ячеек. Затем вы сбросите временную матрицу и снова запустите логику.

Однако мы также должны учитывать, что текст может состоять из нескольких строк. Для этого нужен дополнительный оператор if внутри первого блока if с использованием all. Если у нас есть дополнительная строка текста, которая предшествует предыдущей строке, временная матрица значений все еще должна быть пустой, и поэтому вы должны проверить, пуста ли она, прежде чем пытаться объединить временную матрицу. Если он пуст, не беспокойтесь и просто продолжайте.


После запуска этого кода я получаю для своей матрицы данных следующее:

>> format long g
>> celldisp(data)


data{1} =

                         0             -2.680148e-16                         0
      9.84392531300799e-12              -4.75347e-06              2.216314e-11
      1.00005260577246e-11             -4.835427e-06              2.552497e-11
      1.03137275471577e-11              -4.99934e-06             -3.042096e-12
      1.09401305260241e-11             -5.327165e-06             -1.206968e-11



data{2} =

                         0             -2.680148e-16                         0
      9.84392531300799e-12              -4.75347e-06              2.216314e-11
      1.00005260577246e-11             -4.835427e-06              2.552497e-11
      1.03137275471577e-11              -4.99934e-06             -3.042096e-12
      1.09401305260241e-11             -5.327165e-06             -1.206968e-11

Чтобы получить доступ к определенной «таблице», выполните data{ii}, где ii - это таблица, к которой вы хотите получить доступ, которая была прочитана сверху вниз в вашем текстовом файле.

person rayryeng    schedule 28.01.2016
comment
Такое объединение данных на каждой итерации будет очень медленным. Я бы посоветовал изучить варианты, представленные в этом вопросе SO, чтобы найти варианты, чтобы ускорить это. - person excaza; 29.01.2016
comment
@excaza можешь написать ответ. - person rayryeng; 29.01.2016
comment
Мог бы, но у меня нет MATLAB;) - person excaza; 29.01.2016
comment
@excaza очень плохо пожимает плечами - person rayryeng; 29.01.2016

Самый универсальный способ - читать строку за строкой с помощью TextScan. Если вы хотите ускорить этот процесс, вы можете сначала выполнить фиктивное чтение: т.е. Вы просматриваете все строки без сохранения данных и решаете, какие строки являются текстовыми строками, а какие - числами, записывая быстрое количество строк для каждой. Тогда у вас будет достаточно информации о данных, чтобы быстро просмотреть массивы. Это значительно сократит время, необходимое для хранения данных в ваших новых массивах. Ваш второй цикл - это тот, который фактически считывает данные в массив / ы. Теперь вы должны знать, какие строки нужно пропустить. Вы также можете предварительно выделить массивы в ячейке данных, если хотите.

fid = fopen('file.txt','r');
data = {};
nlines = [];

% now start the loop
k=0;  % counter for data sets

while ~feof(fid)

    line = fgetl(fid);

    % check if is data or text
    if all(ismember(line,' 0123456789+.')) % is it data
        nlines(k) = nlines(k)+1;
    else                                   %is it text
        k=k+1;
        nlines(k) = 0;
    end
end

frewind(fid);  % go back to start of file

% You could preallocate the data array here if you wished

% now get the data
for aa = 1 : length(nlines)
    if nlines(aa)==0;
        continue
    end
    textscan(fid,'%s\r\n',1); % skip textline
    data{aa} = textscan(fid,'%f%f%f\r\n',nlines(k));
end
person Community    schedule 28.01.2016