0

我的目标是将各种文件夹和文本文件中的数据导入matlab。

clear all
main_folder = 'E:\data';
    %Directory of data
TopFolder = dir(main_folder);
    %exclude the first two cells as they are just pointers. 
TopFolder = TopFolder(3:end);
TopFolder = struct2cell(TopFolder);
Name1 = TopFolder(1,:);
    %obtain the name of each folder
dirListing = cellfun(@(x)dir(fullfile(main_folder,x,'*.txt')),Name1,'un',0);
Variables = cellfun(@(x)struct2cell(x),dirListing,'un',0);
FilesToRead = cellfun(@(x)x(1,:),Variables,'un',0);
    %obtain the name of each text file in each folder

这提供了“main_folder”中每个文件夹中每个文本文件的名称。我现在尝试在不使用 for 循环的情况下加载数据(我意识到 for 循环有时会更快,但我的目标是紧凑的脚本)。

我将与 for 循环一起使用的方法是:

for k = 1:length(FilesToRead);
    filename{k} = cellfun(@(x)fullfile(main_folder,Name{k},x),FilesToRead{k},'un',0);
    fid{k} = cellfun(@(x)fopen(x),filename{k},'un',0);
    C{k} = cellfun(@(x)textscan(x,'%f'),fid{k},'un',0);
end

有没有一种完全不使用循环的方法?像 cellfun 中的 cellfun 之类的东西可能吗?

4

2 回答 2

0

是的。这将是非常可怕的,因为 C 依赖于 fid 依赖于文件名。基本思想将是:

deal(feval(@(filenames_fids){filenames_fids{1}, filenames_fids{2}, ...
  <compute C>}, feval(@(filenames){filenames, <compute fid>}, ...
  <compute filenames>)));

让我们从计算文件名开始:

arrayfun(@(x)cellfun(@(x)fullfile(main_folder,Name{k},x),FilesToRead{k},...
  'un',0), 1:length(FilesToRead), 'uniformoutput', 0);

这将为我们提供一个 K×1 的文件名元胞数组。现在我们可以用它来计算fids:

{filenames, arrayfun(@(k)cellfun(@(x)fopen(x),filenames{k},'un',0), ...
  1:length(FilesToRead), 'uniformoutput', 0)};

我们将 fid 与文件名粘贴在一个 K×2 单元数组中,准备传递以计算我们的最终输出:

{filenames_fids{1}, filenames_fids{2}, ...
  arrayfun(@(k)cellfun(@(x)textscan(x,'%f'), ...
  filenames_fid{2}{k},'un',0), 1:length(FilesToRead), 'uniformoutput', 0)}

然后我们将最终的单元格数组放入交易中,以便结果以三个不同的变量结束。

[filenames fid C] = deal(feval(@(filenames_fids){filenames_fids{1}, ...
  filenames_fids{2}, arrayfun(@(k)cellfun(@(x)textscan(x,'%f'), ...
  filenames_fid{2}{k},'un',0), 1:length(FilesToRead), 'uniformoutput', 0)}, ...
  feval(@(filenames){filenames, arrayfun(@(k)cellfun(@(x)fopen(x), ...
  filenames{k},'un',0), 1:length(FilesToRead), 'uniformoutput', 0)}, ...
  arrayfun(@(x)cellfun(@(x)fullfile(main_folder,Name{k},x),FilesToRead{k}, ...
  'un',0), 1:length(FilesToRead), 'uniformoutput', 0))));

Errm...如果您不介意保留filenamesand ,可能有更好的方法来做到这一点fid。也许使用 cellfun 代替 arrayfun 也可以使它更简洁,但是我对 cellfun 不是很好,所以这就是我想出的。我认为for无论如何循环版本更紧凑!(另外,我还没有实际测试过。它可能需要一些调试)。

于 2012-04-13T10:56:10.857 回答
0
folder = 'E:\data';
files = dir(fullfile(folder, '*.txt'));
full_names = strcat(folder, filesep, {files.name});
fids = cellfun(@(x) fopen(x, 'r'), full_names);
c = arrayfun(@(x) textscan(x, '%f'), fids);  % load data here
res = arrayfun(@(x) fclose(x), fids);
assert(all(res == 0), 'error in closing files');

但如果数据是 csv 格式,它会更容易:

folder = 'E:\data';
files = dir(fullfile(folder, '*.txt'));
full_names = strcat(folder, filesep, {files.name});
c = cellfun(@(x) csvread(x), full_names,  'UniformOutput', false);

现在所有数据都存储在c

于 2012-04-13T13:28:13.670 回答