和/或if语句之间的层次结构

时间:2019-06-12 11:57:04

标签: matlab if-statement

我有一个名为data的文件,其中有一部分Data.ensemble,其中前几行如下所示:

                Year Month Day Hour Min Temp
0   1635    1   2009    12  10  22  36  16.28
0   1635    2   2009    12  10  22  37  17.25
0   1635    3   2009    12  10  22  38  16.97
0   1635    4   2009    12  10  22  39  16.69
0   1635    5   2009    12  10  22  40  17.42

我想在12月的每小时0、20、30和40分钟提取温度。我对此编码有麻烦。这就是我正在尝试的:

Month = 12;
Minute = [0 20 30 40];

if Data.ensemble(:, 5) == Month & (Data.ensemble(:, 8) == (Minute(1) | Minute(2) | Minute(3) | Minute(4)))
    Temperature = Data.ensemble(:, 10)
end

这似乎并没有创建Temperature,我希望它只会复制整个列,而不仅仅是复制正确分钟的温度。此外,我不太确定方括号是否在和/或之间使用正确的层次结构。必须始终是12月(12)和分钟(0或20或30或40)之内的时间。

4 个答案:

答案 0 :(得分:3)

您可以使用logical indexing

%dummy data

x = datevec(now+[1:30]+170)

% x =
%
%   2019.0000     11.0000     30.0000     12.0000     56.0000     43.4885
%   2019.0000     12.0000      1.0000     12.0000     56.0000     43.4885
%   2019.0000     12.0000      2.0000     12.0000     56.0000     43.4885
%   2019.0000     12.0000      3.0000     12.0000     56.0000     43.4885
%   2019.0000     12.0000      4.0000     12.0000     56.0000     43.4885
%    ... 

%create a logical index to get each 10th,20th and 30th day of the month in december.
%we can use ismember to check several day at once.
index = ismember(x(:,3),[10,20,30]) & x(:,2) == 12
y     = x(index,:)

% y =
%
%   2019.000     12.000     10.000     12.000     59.000     13.826
%   2019.000     12.000     20.000     12.000     59.000     13.826

如果要使用if else语句,则需要一个for循环来单独检查每一行。

答案 1 :(得分:1)

您已经接近了,但是如果您尝试评估逻辑条件,就会发现它不起作用:

>> Minute(1)|Minute(2)|Minute(3)|Minute(4)
ans = 1

因此(假设我将您的数据存储在变量A中)

>> (A(:,8) == (Minute(1)|Minute(2)|Minute(3)|Minute(4)))
ans =

  0
  0
  0
  0
  0

鉴于:

>> A(:,5) == Month
ans =

  1
  1
  1
  1
  1

我们得到:

>> A(:,5) == Month & (A(:,8)==(Minute(1)|Minute(2)|Minute(3)|Minute(4)))
ans =

  0
  0
  0
  0
  0

这意味着条件永远不会为真,Temperature也永远不会被定义。正确的方法是(或者我应该说一种方法)是使用logical indexing

>> idx = ( A(:,8)==Minute(1)|A(:,8)==Minute(2)|A(:,8)==Minute(3)|A(:,8)==Minute(4)) & A(:,5) == Month

idx =

  0
  0
  0
  0
  1

然后您可以将温度定义为:

>> Temperature = A(idx,9)
Temperature =  17.420

答案 2 :(得分:1)

您可以使用逻辑索引

tf = Data.ensemble(:,5) == Month & any(Data.ensemble(:,8) == Minute, 2);
Temperature = Data.ensemble(tf,9)

查找

ind = find(Data.ensemble(:,5) == Month & any(Data.ensemble(:,8) == Minute, 2));
Temperature = Data.ensemble(ind,9)

注意: find比逻辑索引慢。

说明:

Data.ensemble(:,5) == Month 返回一个逻辑列向量,其中1的条件为true,0为false。对于您的示例,结果将是:

5×1 logical array
   1
   1
   1
   1
   1

Data.ensemble(:,8) == Minute 返回一个逻辑矩阵,其中每一列对应Minute的每个元素。对于您的示例,结果将是:

  5×4 logical array
   0   0   0   0
   0   0   0   0
   0   0   0   0
   0   0   0   0
   0   0   0   1

any(Data.ensemble(:,8) == Minute, 2) :要获得具有1(=分钟条件已匹配)的每一行的1单个逻辑矢量,我们在行(第二个维度)上调用any。对于您的示例,结果将是:

5×1 logical array
   0
   0
   0
   0
   1

通话:

any(Data.ensemble(:,8) == Minute, 2)

短于:

Data.ensemble(:,8) == Minute(1) | Data.ensemble(:,8) == Minute(2) | Data.ensemble(:,8) == Minute(3) | Data.ensemble(:,8) == Minute(4)

答案 3 :(得分:1)

您对logical indexing在MATLAB中的工作方式有误解,但除此之外,您有正确的想法。

表达式(Minute(1) | Minute(2) | Minute(3) | Minute(4))将对标量元素执行logical or。由于它们都是非零(和标量),因此结果始终为1。由于您的分钟数很少为1,因此可能什么也没选择。

表达式Data.ensemble(:, 5) == Month创建一个逻辑数组,其元素数量与Data.ensemble中的行数相同。如果有比示例中显示的更多的数据,则某些元素可能为0。该表达式可能会警告您,因为结果数组的逻辑值不明确:

  1. 如果任何元素为1,则可以将其设置为1
  2. 如果任何元素为0,则可以将其设置为0
  3. 如果数组只是非空的,则可以将其设置为1
  4. 在上下文中有意义的任何其他标准...

即使最终条件为1,表达式Temperature = Data.ensemble(:, 10)也会将Temperature设置为整个第10列。

您正在寻找将if语句的更正版本应用于数据的每一行。诀窍是使用逻辑数组对条件进行编码,然后使用该逻辑数组作为索引:

 month_is_12 = (Data.ensemble(:, 5) == Month);
 minute_is_good = ismember(Data.ensemble(:, 8), Minute);

ismember将对照Minute数组检查第8列的每个元素,以确定它是否与任何元素匹配。等同于做

minute_is_good = ((Data.ensemble(:, 8) == Minute(1)) | (Data.ensemble(:, 8) == Minute(2)) | (Data.ensemble(:, 8) == Minute(3)) | (Data.ensemble(:, 8) == Minute(4)));

不仅ismember看起来更好,而且它使您可以修改Minute的大小而不必修改实际代码。

现在,您不需要if即可获取所需的数据:

Temperature = Data.endemble(month_is_12 & minute_is_good);