【问题标题】:find range between two specific times in matlab在matlab中找到两个特定时间之间的范围
【发布时间】:2013-02-26 15:46:18
【问题描述】:

我有一个年度数据集:

Jday = datenum('2009-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
    datenum('2009-12-31 23:00','yyyy-mm-dd HH:MM');
DateV = datevec(Jday);
dat = 1+(10-1).*rand(length(Jday),10);
noise = 10*sin(2*pi*Jday/32)+20;
for i = 1:size(dat,2);
    dat2(:,i) = dat(:,i)+noise';
end

表示通过水柱记录的温度测量值。我想计算每天 06:00 到 18:00 之间的温度范围,以便最终得到每个深度的 365 个值,因此最终矩阵为 365x10。

我可以通过以下方式指定个别日期:

[~,~,b] = unique(DateV(:,2:3),'rows');

但我不知道如何只考虑上午 06:00 到晚上 18:00 之间记录的值。谁能提供一些关于这样做的最佳方法的信息?

修正:略长的答案

Jday = datenum('2009-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
    datenum('2009-12-31 23:00','yyyy-mm-dd HH:MM');
DateV = datevec(Jday);
dat = 1+(10-1).*rand(length(Jday),10);
noise = 10*sin(2*pi*Jday/32)+20;
for i = 1:size(dat,2);
    dat2(:,i) = dat(:,i)+noise';
end

for i = 1:size(dat2,2);
    data = [DateV(:,4),dat2(:,i)]; % obtain all hours from DateV array

    dd = find(data(:,1) == 6); % find 06:00
    dd(:,2) = find(data(:,1) == 18); % find 18:00

    for ii = 1:size(dd,1);
        result(ii,i) = range(data(dd(ii,1):dd(ii,2),2)); % calculate range
    end
end

【问题讨论】:

  • 我不明白你想如何只使用一个值来表示温度范围
  • 温度范围在每天 06:00 到 18:00 之间,因此有 13 个值
  • 这还不清楚。您希望得到一个 365×10 矩阵。我推断 365 对应天数,10 是测量次数。这个 06:00-18:00 的温度在哪里起作用?是否要对该时间段内的值进行平均?
  • 修正矩阵。如果您查看变量 DateV,它将以小时为单位显示一天中的时间“DateV(:,4)”,因此对于第一天,即 2009-01-01,我想计算第 7 行和第 18 行之间的温度范围即分别为 06:00 和 18:00。因此,对于第一天和第一次测量(深度),我可以通过以下方式计算:range(dat2(7:18,1)) 然后我需要对第二列然后第三列重复此操作,依此类推,然后重复此过程从第 25 行开始的第二天。这是否更清楚?
  • 我想是的。我已经发布了答案,希望对您有所帮助。

标签: matlab


【解决方案1】:

如果range 被输入一个矩阵,它会独立地对每一列进行操作。我们可以使用它来准备一个矩阵,其中每列包含 06:00 到 18:00 时间间隔的值,然后应用 range

  1. 棘手的部分是操纵您的 365x24×10 矩阵以使列正确:

    A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
    

    这应该会产生 3-D 24x10x365 矩阵,可以从中提取第 7 到 18 行。

  2. 下一步是应用 range 并将结果转换回二维 365x10 矩阵:

    result = permute(range(A(7:18, :, :)), [3, 2, 1]);
    

因此,完整的解决方案是:

A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
result = permute(range(A(7:18, :, :)), [3, 2, 1]);

编辑
为了使解决方案更加通用,您可以使用DateV 来获取所需行的索引:

idx = DateV(1:24, 4) >= 6 & DateV(1:24, 4) < 18;

然后像这样在解决方案中使用它:

A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
result = permute(range(A(idx, :, :)), [3, 2, 1]);

【讨论】:

  • 很好的解决方案。尽管可以使代码更通用,即代码使用提供的日期向量来查找指定时间段的行号,而不是定义行 7:18。如果数据不是在给定日期的午夜开始,这将避免错误。
  • @user1155751 我会看看我能做什么:-)
  • 太棒了。我正在考虑按照以下方式做一些事情——newDateV = permute(reshape(DateV',[size(DateV,2),length(unique(DateV(:,4))),... length(unique(floor (Jday-datenum(DateV(1,1),0,0))))]),[2,1,3]);找到我们想要的一天中的时间,然后用 newDateV 中这些时间的索引替换 7:18,尽管这似乎是一个冗长的方法。
  • 我已经修改了我的原始帖子以提供解决方案。我展示的方法按要求工作,但感觉我的程序过于复杂。
  • @user1155751 我已经修改了解决方案。这是你想要的吗?请注意,它仅使用 DateV 的前 24 个值并将它们应用于整个日期集。如果不同日期的此类时间段包含不同数量的样本,则无法像我建议的那样重塑矩阵,需要另一种解决方案。
【解决方案2】:

1987 年 1 月 1 日至 1987 年 12 月 31 日之间的每小时日期范围:

start_date = datenum(1987,01,01,00,00,00)
end_date = datenum(1987,12,31,23,00,00)
interval = datenum(1987,0,0,1,0,0)-datenum(1987,0,0,0,0,0) % 1 hour interval

date_range = [start_date:interval:end_date]

非常简单,也适用于闰年。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 2019-04-17
    • 2012-10-26
    相关资源
    最近更新 更多