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

Conditional text import or import by header name - MATLAB

有没有办法在 MATLAB 中执行条件文本导入?例如使用以下格式的 tab-delimited.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 文件中包含的 headers 导入和处理数据?例如在上例中导入 'Type' 'A' 'B' 和 'D' 而忽略 'C' 和 'E'。如果输入文件格式灵活,有时添加额外的列意味着它们的相对位置发生变化,则需要这样做。

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

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

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

然后您可以将 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))

希望对您有所帮助。

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

这是il_raffa的回答中给出的解决方案。请注意,您实际上无论如何都必须读取整个文件,因为您使用 fgetl 读取了整行,然后在其上使用了 textscan!所以它肯定不会比读取整个文件然后过滤它更快(尽管它可能更多memory-efficient)。

你真正想要的是一个字符一个字符地读取文件,如果你能确定你不会读取它,则中止每一行,基于 "A" 列的值。

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

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

  1. 文件采用逗号或制表符分隔格式
  2. 它有 header 行

然后您可以阅读 header 行(使用 fgetl),它会告诉您有多少列以及它们的名称。然后,您可以使用该信息构建对 textscan 的调用,该调用将读取分隔的列,并过滤掉 header 与您的需要不匹配的列。一个简单的版本可能看起来像 -

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