我有一个名为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)之内的时间。
答案 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,表达式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);