如果在另一个数组中满足条件,如何操作一个数组中的数据?

How to maniplulate data in one array if conditions are met in another array?

我有一个数字数据数组,还有另一个包含该数据的字符串 headers。这两个数组根据 header 与哪一列匹配。我想为 headers 数组中的每一列编写一个 if 语句,例如,如果第 1 列中的字符串值等于 'header1',则从数据数组中取出第 1 列并将所有值相乘乘以 10(或对每个单元格中的数据应用某些函数)。如果它等于不同的字符串,则执行其他操作,然后转到 header 数组中的下一个字符串并重复该过程。

这是我目前所掌握的。 names 是包含 1 列和一些字符串 headers 的数组,Data 是新的数据文件,而 dataToRead 是原始数据数组。必须有更好的方法来做到这一点,我可能有 1 到 20 formulas/headers 的任何地方,所以如果 else 语句看起来是错误的,那么赚一百万。 在某个地方,我希望有一个公式存储库,可以应用于每个字符串案例,这样我就可以让它循环,而不是有 20 个 if 语句。那可能吗?

这段代码似乎工作得很好,但这不是解决这个问题的最佳方法。

for n=1:length(names)
if names{:,n}=='header1'
Data(:,n)=3*DataToRead(:,n+1); %I have a time stamp in column 1 i dont want to act upon
else
if names{:,n}=='header2'
Data(:,n)=4*DataToRead(:,n+1)
else
if names{:,n}=='header4'
Data(:,n)=0*DataToRead(:,n+1)
end 
end
end
end
headers = {'header1', 'header2', 'header4'};
for n = 1:length(names)
   headerstring = names{:,n};
   [temp, N] = max(strcmp(headerstring, headers));
   % // N now contains which in the list of 'headers', 'headerstring' matches.
   % // strcmp(string, stringcellarray) returns a vector of 0s and 1s ...
   % // ... corresponding to if string equals stringcellarray(i)
   Data(:, n) = myfunc(DataToRead(:,n+1), N);
end

然后在另一个文件中,您将拥有:

function val = myfunc(x, N)
    switch N
        case 1
             val = 3.0 * x;
        case 2
             val = 4.0 * x;
        case 3
             val = 0.0 * x;
        otherwise
             error('Case not found');
    end
end

除非您可以用数字 'n' 为每个 header 编制索引,并将您需要编写的每个公式与 'n' 相关联,否则很遗憾,您可能不得不 hand-code 每个公式。

顺便说一下,'names' 是什么还不清楚。它是一维字符串数组吗? 'names'.

中的每个字符似乎都有一个单元格

此外,请注意 'if ... == ...' 带有字符串的语句。它 return 是每个字符的 true/false 向量,并且 'if' 隐式检查是否所有字符都为真。请改用 'strcmp'。

编辑: 实际上,比使用 max 函数更简洁的方法是使用 find 函数。 使用:

N = find(strcmp(headerstring, headers), 1);

maxfind 语句背后的想法是找到 0/1 向量 return 中第一个 non-zero 元素的索引strcmp 函数。

strcmp 函数将 return 大小为 size(headers) 的向量。在 headersheaderstring 匹配的所有位置,它将有等于 1 的条目。剩余条目将为零。

警告:要使此特定代码正常工作,headers 必须是元胞数组(如向量)而不是元胞矩阵(二维或更多维) ).

max语句的解释:

[temp, N] = max(strcmp(headerstring, headers));

此函数找到索引 N,使头串匹配 headers{N}。完成方式如下:

  • strcmp(headerstring, headers) returns 一个 0/​​1 向量对应于 headerstring 匹配 headers.
  • max 和 1 return 值显然会 return 1。但是我们想要那个的index。所以我们使用 max 和 2 个输出。第一个 temp 只是 1。另一个输出参数包含其中的 index(请参阅 MATLAB 关于 max 的文档)
  • find函数一步完成同样的事情。用那个。

编辑:我从头开始重写 post 以更好地解释细节。

此代码将满足您的需要。请继续阅读以获取解释。

nNames = length(names);
nHeaders = length(headers);
rpmNames = repmat(names',1,nHeaders);
rpmHeaders = repmat(headers,nNames,1);
I = cellfun( @isequal, rpmNames, rpmHeaders  );
[idx ~] = ind2sub( size(I), find(I) );
output = bsxfun(@times,Data,multipliers(idx));

这个过程有 4 个输入:

  1. 一个名为 names1xn 元胞数组列出所有 n 可能的 headers
  2. 一个名为 multipliers1xn 数值数组给出了 n 个乘数以及可能的 header 个名字
  3. 一个名为 headers1xh 元胞数组列出了 names 中 header 的一些组合,对应于 h 列=32=]矩阵
  4. 一个名为 DataDxh 数值数据矩阵;行数 D 无关紧要

如果您需要复制一些内容,我将使用以下示例输入:

names = {'h1';'h2';'h3';'h4'};
multipliers = [3 4 0 10]; 
headers = {'h1','h2','h1','h4','h1','h3','h1','h2'};
Data = [ 
      9     4     2     5     9     5     5    10
     10     6     1     1     7    10     6     0
      4     3     3     3     5     5     7     9
      1     6     3     8     6     5     4     9
      3     7     4     0     2     2     4     8 ];

下面是一个walk-through的代码:

首先获取 header 类型的数量 nNames 和实际 header 的数量 nHeaders

nNames = length(names);
nHeaders = length(headers);

我们想根据names中对应header的索引给headers中的条目分配编号。首先,我们在元胞数组上使用 repmat

rpmNames = repmat(names',1,nHeaders)
rpmHeaders = repmat(headers,nNames,1)

这应该打印出以下内容:

rpmNames = 

    'h1'    'h1'    'h1'    'h1'    'h1'    'h1'    'h1'    'h1'
    'h2'    'h2'    'h2'    'h2'    'h2'    'h2'    'h2'    'h2'
    'h3'    'h3'    'h3'    'h3'    'h3'    'h3'    'h3'    'h3'
    'h4'    'h4'    'h4'    'h4'    'h4'    'h4'    'h4'    'h4'

rpmHeaders = 

    'h1'    'h2'    'h1'    'h4'    'h1'    'h3'    'h1'    'h2'
    'h1'    'h2'    'h1'    'h4'    'h1'    'h3'    'h1'    'h2'
    'h1'    'h2'    'h1'    'h4'    'h1'    'h3'    'h1'    'h2'
    'h1'    'h2'    'h1'    'h4'    'h1'    'h3'    'h1'    'h2'

接下来我们使用 element-by-element isequal() 检查 headers 对应于我们的 names 的位置。我们可以使用 cellfun().

来做到这一点
I = cellfun( @isequal, rpmNames, rpmHeaders  )

这打印出来

I =

     1     0     1     0     1     0     1     0
     0     1     0     0     0     0     0     1
     0     0     0     0     0     1     0     0
     0     0     0     1     0     0     0     0

您可以看到,对于任何列,1' 的行索引告诉我们 names 中 header 名称的数字索引。我们可以使用 find 获取行索引来定位 1 条目,并使用 ind2sub

获取行
[idx ~] = ind2sub( size(I), find(I) )

这是数字索引。

idx =

     1     2     1     4     1     3     1     2

因为这些是names中header的索引,我们也可以在multipliers中使用这些索引,因为位置对应于names。要查看此内容,请键入 multipliers(idx)

ans =

     3     4     3    10     3     0     3     4

最后一步只是将这些乘数应用于 Data 的列。我们可以使用 bsxfun 来做到这一点,它基本上同时执行 repmat 和 element-by-element 运算符。我们将使用 @times 运算符进行乘法运算。

output = bsxfun(@times,Data,multipliers(idx))

这给了我们想要的输出。

27    16     6    50    27     0    15    40
30    24     3    10    21     0    18     0
12    12     9    30    15     0    21    36
 3    24     9    80    18     0    12    36
 9    28    12     0     6     0    12    32