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

时间:2015-03-02 19:05:02

标签: arrays string matlab cell-array

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

这是我到目前为止所拥有的。 names是包含1列和一些字符串头的数组,Data是新数据文件,而dataToRead是原始数据数组。必须有一个betetr方法来做到这一点,我可能有1到20个公式/标题,所以制作一百万if 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

2 个答案:

答案 0 :(得分:2)

编辑:我从头开始重新发布帖子以更好地解释详细信息。

此代码将满足您的需求。继续阅读以获得解释。

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. 名为1xn的{​​{1}}单元格数组,其中列出了所有names个可能的标题
  2. 名为n的{​​{1}}数字数组,提供1xn倍增因子以及可能的标题名称
  3. 名为multipliers的{​​{1}}单元格数组列出了n中某些标题的组合,对应1xh矩阵中的headers
  4. names数字数据矩阵h;行数Data无关紧要
  5. 如果您需要复制内容,我将使用以下示例输入:

    Dxh

    以下是代码的演练:

    首先获取标题类型Data的数量和实际标题数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 ];
    

    我们希望根据nNames中相应标头的索引为nHeaders中的条目分配数字。首先,我们在单元格数组上使用nNames = length(names); nHeaders = length(headers);

    headers

    这应该打印出以下内容:

    names

    接下来,我们使用逐个元素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' 的对应位置。我们可以使用headers执行此操作。

    names

    打印出来

    isequal()

    对于任何列,您都可以看到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获取行

    find

    以下是数字索引。

    1

    由于这些是ind2sub中标题的索引,我们也可以在[idx ~] = ind2sub( size(I), find(I) ) 中使用这些索引,因为这些位置对应于idx = 1 2 1 4 1 3 1 2 。要查看此内容,请键入names

    multipliers

    最后一步是将这些乘数应用于names的列。我们可以使用multipliers(idx)执行此操作,ans = 3 4 3 10 3 0 3 4 基本上执行Data,然后一次执行元素操作。我们将bsxfun运算符用于乘法。

    repmat

    这为我们提供了理想的输出。

    @times

答案 1 :(得分:1)

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'并且将你需要写的所有公式联系起来,很遗憾,你可能不得不手工编写每个公式。

目前还不清楚名称是什么'顺便说一下。它是一维字符串数组吗?看起来你的名字中有每个角色都有一个单元格。

另外,请小心,如果...... == ......'带字符串的语句。它为每个字符返回一个真/假的向量,如果'隐式检查是否所有都是真的。使用' strcmp'代替。

编辑:实际上比使用max功能更清晰的方法是使用find功能。 使用:

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

maxfind语句背后的想法是找到strcmp函数返回的0/1向量中第一个非零元素的索引。

strcmp函数将返回大小为size(headers)的向量。在1匹配headers的所有位置,其条目均为headerstring。其余条目将为零。

警告:要使此特定代码生效,标题必须是单元格数组(如矢量),而不是单元格矩阵(2维或更多)。

对max语句的解释:

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

此函数查找索引N,使得headtring与标题{N}匹配。它完成如下:

  • strcmp(headerstring,headers)返回0/1向量,对应headerstring匹配headers的位置。
  • 如果
  • max返回1,那么显然会返回1。但我们想要索引。所以我们使用max和2个输出。第一个temp只是1。另一个输出参数包含index的内容(参见MATLAB&#39}关于max的文档)
  • find功能在一个步骤中执行相同操作。使用它。