按标题名称导入或导入条件文本 - MATLAB

时间:2015-08-21 16:06:27

标签: matlab textscan

有没有办法在MATLAB中执行条件文本导入?例如使用以此格式的制表符分隔的.txt文件:

Type    A   B   C   D   E
 A    5000  2   5   16  19
 A    5000  3   4   5   4
 A    5000  4   1   4   5
 B    500   19  8   2   7
 B    500   18  9   8   1
 B    500   2   9   13  2
 B    100   3   10  15  9
 B    5000  4   15  14  10

是否有方法只导入列A包含'5000'的那些行?

这优先于导入整个.txt文件并在之后分离数据,因为实际上,我的文本文件相当大(每个大约200MB) - 但如果有办法快速完成,那么这也是一个合适的解决方

或者,是否有一种方法(类似于R),您可以使用.txt文件中包含的标头导入和处理数据?例如导入'Type''A''B'和'D',而在上例中忽略'C'和'E'。如果输入文件格式灵活,并且添加了其他列,有时意味着它们的相对位置发生变化,则需要这样做。

2 个答案:

答案 0 :(得分:1)

您可以尝试逐行读取输入文件,检查该行是否包含参考列中的参考值(本例中为5000)(在本例中为第2列)。

如果是这样,您可以存储输入,否则,您将其丢弃。

在以下代码中,您可以根据模板在代码的开头定义参考值和参考列。

然后,您可以将cellarray输出转换为array

% Define the column index
col_idx=2
% Define the reference value
ref_value=5000
% Open input file
fid=fopen('in.txt');
% Read header
tline = fgetl(fid);
% Initialize conter
cnt=0;
% Initialize output variable
data=[];
% Read the file line by line
while 1
   % Read the line
   tline = fgetl(fid);
   % Check for the end of file
   if ~ischar(tline)
      break
   end
   % Get the line field
   c=textscan(tline,'%c%f%f%f%f%f')
   % If the seconf field contains the ref value, then store the inout data
   if(c{col_idx} == ref_value)
      data=[data;c]
   end
end
fclose(fid);
% Convert cell 2 array
c=data(:,2:end)
num_data=cell2mat(c)
% Convert first column to char
lab=char(data(:,1))

希望这有帮助。

答案 1 :(得分:0)

函数fgetl用于从文本文件中读取单行,因此一个选项是编写一个循环,使用fgetl连续读取一行并检查第一列是否包含" 5000"在决定是否将其包含在您的数据集中之前。

这是il_raffa答案中提出的解决方案。请注意,您实际上必须阅读整个文件,因为您使用fgetl阅读整行,然后使用textscan!所以它肯定不会比读取整个文件然后过滤它更快(尽管它可能更节省内存)。

你真正想要的是逐个字符地阅读文件,如果你可以根据" A"的价值确定你不会阅读它,就会中止每一行。列。

如果你正在编写C或其他低级语言,这可能比导入整个文件并在之后过滤它更快。但是,由于MATLAB引入的开销,几乎可以肯定更快更容易读取整个文件并在以后过滤它。 textscan函数在读取分隔文件方面非常好(而且速度快),200MB实际上并不那么大(例如,它可以很舒适地放入任何现代计算机的内存中)。您应该确保在读取后过滤每个数据集,而不是读取所有数据集然​​后将它们全部过滤。

关于您是否可以有选择地导入列,问题的第二部分 - MATLAB没有提供内置的方法来执行此操作。但是,如果您可以对文件格式做一些假设,那就不是那么棘手了。如果我们假设

  1. 文件采用逗号或制表符分隔格式
  2. 它有一个标题行
  3. 然后你可以阅读标题行(使用fgetl),它会告诉你有多少列,以及它们的名称。然后,您可以使用该信息构建对textscan的调用,该调用将读取分隔的列,并过滤掉其标题不符合您需要的列。这个的简单版本可能看起来像 -

    function columns = import_columns(filename, headers)
    
      fid = fopen(filename);
      hdr = fgetl(fid);
      column_headers = regexp(hdr, '\t', 'split'); % split on tabs
    
      num_cols = length(column_headers);          
      format_str = repmat('%s', 1, num_cols); % create a string like '%s%s%s%s'
      columns = textscan(fid, format_str, 'Delimiter', '\t');
      fclose(fid);
    
      required_cols = ismember(column_headers, headers);
      columns(~required_cols) = []; % remove the columns you don't need
    
    end