将大型奇怪格式的数据文本文件读入MATLAB

时间:2014-11-10 07:23:45

标签: matlab text-files cell-array

需要阅读一个充满奇怪格式数据的巨大文本文件。格式如下:

//Header with Title Info

//Header with Test1 Info
//More Test1 Info
0,-156.875956035285
1.953125,-4.82866496038806
3.90625,-8.93502887648155
5.859375,-9.76964479822559
7.8125,-14.9767168331976
9.765625,-16.9949034672061
11.71875,-19.2709033739316
13.671875,-18.9948581866681

//Header with Test2 Info
//More Test2 Info
0,-156.875956035285
1.953125,-4.82866496038806
3.90625,-8.93502887648155
5.859375,-9.76964479822559
7.8125,-14.9767168331976
9.765625,-16.9949034672061
11.71875,-19.2709033739316
13.671875,-18.9948581866681

//Header with Test3 Info
//More Test3 Info
0,-156.875956035285
1.953125,-4.82866496038806
3.90625,-8.93502887648155
5.859375,-9.76964479822559
7.8125,-14.9767168331976
9.765625,-16.9949034672061
11.71875,-19.2709033739316
13.671875,-18.9948581866681

// End of Data

这是它的要点,除了每个标题下有大约25,000个条目而不是8个。我运行25个测试,需要将它们一起平均为一组数据。

基本上,我想解析这个序列中的数据:

  1. 跳过第一行
  2. 识别空行,转到下一个
  3. 检查"数据结束"
  4. 如果不是结束,则跳过当前行和下一行
  5. 为当前测试数据集创建新数组
  6. 读取数据直到达到空行,然后返回步骤2
  7. 然后,我想以最有效的方式将所有这些集合平均化。

    我在阅读数据时遇到了问题。我知道我可以使用csvread,或者更通用的函数来读取分隔值,但是我很难找到一种优雅而简洁的方法来完成所有事情。

    我从这开始:

    function [ data ] = graph( input_args )
    %Plot data
    
    myData = fopen('mRoom_fSweep_25points_center.txt');
    data = textscan(myData,'%s');
    fclose(myData);
    length(data)
    end
    

    我想我可以找到这个字符串数组的长度,并为整个操作列表设计一个for循环,但我无法超越这一点:输出一直给我这个:

    ans = 
        {772321x1 cell}
    

    我无法使用。当我尝试将它存储在一个变量中时,它给出的值为1.我在这里找不到像单元数组一样奇怪的东西吗?

1 个答案:

答案 0 :(得分:4)

我假设您需要“测试信息”行中的信息?

如果是这样,您需要使用两种不同的模式运行textscan:一种用于选择信息行,另一种用于读取数据:

 info(1, end+1) = textscan(fid, '//%s','Delimiter', '');
 data(1, end+1) = textscan(fid, '%f, %f', 'CollectOutput', true);

下面是我如何用循环和错误处理来包装它:

% [info, data] = read_data(file_name): Read a file in funky format
% 
% info and data are cells of same size
function [info, data] = read_data(file_name)
    [fid, msg] = fopen(file_name);
    if fid<0
        error('Unable to open file "%s": %s', file_name, msg);
    end
    % close the file no matter how we exit this funciton (error,
    % ctrl-c,...)
    finalize = onCleanup(@() fclose(fid));

    info = cell(1,0);
    data = cell(1,0);
    while true
        info(1, end+1) = textscan(fid, '//%s','Delimiter', '');
        data(1, end+1) = textscan(fid, '%f, %f', 'CollectOutput', true);

        if strcmpi(info{1,end}{end}, 'End of Data')
            % End of data reached, exit here
            info = info(1:end-1);
            data = data(1:end-1);
            break;
        end
        if isempty(data{1,end})
            % Empty data, but not 'End of data' marker.
            % Replace this error with break to accept files with missing
            % "end of data" tags
            error('Empty data before "End of Data" line')
        end
    end
end

然后,您可以按如下方式读取文件并计算平均值:

>> [info, data] = read_data('foo.txt')
info = 
    {3x1 cell}    {2x1 cell}    {2x1 cell}
data = 
    [8x2 double]    [8x2 double]    [8x2 double]


>> info{3}
ans = 
    'Header with Test3 Info'
    'More Test3 Info'

>> all_data = cellfun(@(d) d(:,2), data, 'UniformOutput', false); all_data = [all_data{:}]
all_data =
 -156.8760 -156.8760 -156.8760
   -4.8287   -4.8287   -4.8287
   -8.9350   -8.9350   -8.9350
   -9.7696   -9.7696   -9.7696
  -14.9767  -14.9767  -14.9767
  -16.9949  -16.9949  -16.9949
  -19.2709  -19.2709  -19.2709
  -18.9949  -18.9949  -18.9949

>> mean(all_data, 2)
ans =
 -156.8760
   -4.8287
   -8.9350
   -9.7696
  -14.9767
  -16.9949
  -19.2709
  -18.9949