我有一个数值数据数组,我有另一个数据的字符串标题。这两个数组匹配哪个标题与哪个列匹配。我想编写一个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
答案 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个输入:
1xn
的{{1}}单元格数组,其中列出了所有names
个可能的标题n
的{{1}}数字数组,提供1xn
倍增因子以及可能的标题名称multipliers
的{{1}}单元格数组列出了n
中某些标题的组合,对应1xh
矩阵中的headers
列names
数字数据矩阵h
;行数Data
无关紧要如果您需要复制内容,我将使用以下示例输入:
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);
max
和find
语句背后的想法是找到strcmp
函数返回的0/1向量中第一个非零元素的索引。
strcmp
函数将返回大小为size(headers)
的向量。在1
匹配headers
的所有位置,其条目均为headerstring
。其余条目将为零。
警告:要使此特定代码生效,标题必须是单元格数组(如矢量),而不是单元格矩阵(2维或更多)。
对max语句的解释:
[temp, N] = max(strcmp(headerstring, headers));
此函数查找索引N,使得headtring与标题{N}匹配。它完成如下:
headerstring
匹配headers
的位置。max
返回1,那么显然会返回1
。但我们想要索引。所以我们使用max
和2个输出。第一个temp
只是1
。另一个输出参数包含index
的内容(参见MATLAB&#39}关于max
的文档)find
功能在一个步骤中执行相同操作。使用它。