【问题标题】:Group variables based on lengths of specific arrays根据特定数组的长度对变量进行分组
【发布时间】:2017-03-07 19:51:19
【问题描述】:

我在数据集中有一长串变量,其中包含多个具有不同采样率的time 通道,例如time_1time_2TIMETime 等。还有多个其他取决于这些时间中的任何一个的变量。

我想列出所有可能包含“时间”的频道(工作区中不区分大小写的部分字符串搜索),并根据变量,然后将它们与变量的值组合在一个结构中以供以后分析。

例如:

  Name                     Size              Bytes  Class     

  ENGSPD_1            181289x1             1450312  double              
  Eng_Spd              12500x1              100000  double              
  Speed                41273x1              330184  double              
  TIME                 41273x1              330184  double              
  Time                 12500x1              100000  double              
  engine_speed_2        1406x1               11248  double              
  time_1              181289x1             1450312  double              
  time_2                1406x1               11248  double 

在这种情况下,我有 4 个具有不同名称和大小的时间通道和 4 个速度通道,它们分别属于这些时间通道。

whos 函数区分大小写,它只会返回变量的名称,而不是变量的值。

【问题讨论】:

  • 将动态命名的变量放入结构体中,并使用结构体的字段。哦等等,我已经回答了你之前的问题......
  • 与其继续拼凑脆弱的 hackey 代码来尝试让这个实现工作,我强烈建议你接受之前给出的建议,停止尝试走这条路。从头开始,以一种健壮的方法编写代码,不需要所有这些废话,充其量,在您更改数据的某些内容时会破坏。这很可能会导致返回错误数据。

标签: matlab struct size grouping


【解决方案1】:

作为序言,我将回应我上面的评论以及这里的人们之前的 cmets 以及您的其他类似问题:

请停止尝试以这种方式操纵您的数据

一开始可能是有道理的,但是鉴于您迄今为止在 SO 上提出的问题,这不是您第一次遇到试图将所有内容整合在一起的问题,如果您继续这样下去,那就不是将是最后一个。这种方法极易出错、不可靠且不可预测。该过程的每一步都要求您对无法保证的数据做出假设(数据匹配的大小、变量的存在和可预测的命名等)。与其试图想出创造性的方法来破解数据,不如从头开始并以可预测的方式输出数据。这可能需要一些时间,但我保证它会在未来节省时间,并且对于在 6 个月内查看此内容并试图弄清楚发生了什么的人来说,这将是有意义

例如,将变量输出为:

outputstructure.EngineID.time = sometimeseries;
outputstructure.EngineID.speed = somedata;

EngineID 可以是任何个有效的变量名。这很简单,它将您的数据永久而可靠地链接在一起。


话虽如此,以下内容将为您的数据集带来少量的理智:

% Build up a totally amorphous data set
ENGSPD_1       = rand(10, 1);
Eng_Spd        = rand(20, 1);
Speed          = rand(30, 1);
TIME           = rand(30, 1);
Time           = rand(20, 1);
engine_speed_2 = rand(5, 1);
time_1         = rand(10, 1);
time_2         = rand(5, 1);

% Identify time and speed variable using regular expressions
% Assumes time variables contain 'time' (case insensitive)
% Assumes speed variables contain 'spd', 'sped', or 'speed' (case insensitive)
timevars = whos('-regexp', '[T|t][I|i][M|m][E|e]');
speedvars = whos('-regexp', '[S|s][P|p][E|e]{0,2}[D|d]');

% Pair timeseries and data arrays together. Data is only coupled if
% the number of rows in the timeseries is exactly the same as the
% number of rows in the data array.
timesizes  = vertcat(speedvars(:).size);  % Concatenate timeseries sizes
speedsizes = vertcat(timevars(:).size);  % Concatenate speed array sizes

% Find intersection and their locations in the structures returned by whos
% By using intersect we only get the data that is matched
[sizes, timeidx, speedidx] = intersect(timesizes(:,1), speedsizes(:,1));

% Preallocate structure
ndata = length(sizes);
groupeddata(ndata).time = [];
groupeddata(ndata).speed = [];

% Unavoidable (without saving/loading data) eval loop :|
for ii = 1:ndata
    groupeddata(ii).time  = eval('timevars(timeidx(ii)).name');
    groupeddata(ii).speed = eval('speedvars(speedidx(ii)).name');
end

eval 方法,根据请求:

ENGSPD_1       = rand(10, 1);
Eng_Spd        = rand(20, 1);
Speed          = rand(30, 1);
TIME           = rand(30, 1);
Time           = rand(20, 1);
engine_speed_2 = rand(5, 1);
time_1         = rand(10, 1);
time_2         = rand(5, 1);

save('tmp.mat')
oldworkspace = load('tmp.mat');
varnames = fieldnames(oldworkspace);

timevars = regexpi(varnames, '.*time.*', 'match', 'once');
timevars(cellfun('isempty', timevars)) = [];
speedvars = regexpi(varnames, '.*spe{0,2}d.*', 'match', 'once');
speedvars(cellfun('isempty', speedvars)) = [];

timesizes = zeros(length(timevars), 2);
for ii = 1:length(timevars)
    timesizes(ii, :) = size(oldworkspace.(timevars{ii}));
end
speedsizes = zeros(length(speedvars), 2);
for ii = 1:length(speedvars)
    speedsizes(ii, :) = size(oldworkspace.(speedvars{ii}));
end

[sizes, timeidx, speedidx] = intersect(timesizes(:,1), speedsizes(:,1));

ndata = length(sizes);
groupeddata(ndata).time = [];
groupeddata(ndata).speed = [];

for ii = 1:ndata
    groupeddata(ii).time  = oldworkspace.(timevars{timeidx(ii)});
    groupeddata(ii).speed = oldworkspace.(speedvars{speedidx(ii)});
end

请参阅this gist 了解时间安排。

【讨论】:

  • @excaza 美丽的解决方案。非常感谢您的指导。
  • 你的解释很完整,特别是非eval的解决方案很有趣!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 1970-01-01
  • 2014-06-07
  • 2016-10-22
  • 2021-07-08
  • 2022-07-11
相关资源
最近更新 更多