如果在另一个数组中满足条件,如何操作一个数组中的数据?
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);
max
和 find
语句背后的想法是找到 0/1 向量 return 中第一个 non-zero 元素的索引strcmp
函数。
strcmp
函数将 return 大小为 size(headers)
的向量。在 headers
与 headerstring
匹配的所有位置,它将有等于 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 个输入:
- 一个名为
names
的 1xn
元胞数组列出所有 n
可能的 headers
- 一个名为
multipliers
的 1xn
数值数组给出了 n
个乘数以及可能的 header 个名字
- 一个名为
headers
的 1xh
元胞数组列出了 names
中 header 的一些组合,对应于 h
列=32=]矩阵
- 一个名为
Data
的 Dxh
数值数据矩阵;行数 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
我有一个数字数据数组,还有另一个包含该数据的字符串 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);
max
和 find
语句背后的想法是找到 0/1 向量 return 中第一个 non-zero 元素的索引strcmp
函数。
strcmp
函数将 return 大小为 size(headers)
的向量。在 headers
与 headerstring
匹配的所有位置,它将有等于 1
的条目。剩余条目将为零。
警告:要使此特定代码正常工作,headers 必须是元胞数组(如向量)而不是元胞矩阵(二维或更多维) ).
max语句的解释:
[temp, N] = max(strcmp(headerstring, headers));
此函数找到索引 N,使头串匹配 headers{N}。完成方式如下:
- strcmp(headerstring, headers) returns 一个 0/1 向量对应于
headerstring
匹配headers
. max
和 1 return 值显然会 return1
。但是我们想要那个的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 个输入:
- 一个名为
names
的1xn
元胞数组列出所有n
可能的 headers - 一个名为
multipliers
的1xn
数值数组给出了n
个乘数以及可能的 header 个名字 - 一个名为
headers
的1xh
元胞数组列出了names
中 header 的一些组合,对应于h
列=32=]矩阵 - 一个名为
Data
的Dxh
数值数据矩阵;行数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