【问题标题】:index a moving range索引移动范围
【发布时间】:2012-05-06 05:03:56
【问题描述】:

我试图在我的数据集中获取每年的最大值。数据在一列中,按每日时间步长排列。 如何从前 365 行中获取最大值,然后从接下来的 365 行中获取最大值? 我在想这样的事情:

years=31;
for i=1:years
peak(i)=max(data(i:365*i,2))
end

但当 i=2 时,范围应为 366:730 等。 数据矩阵是 11322x7 双倍,我需要第 2 列。

【问题讨论】:

    标签: matlab indexing


    【解决方案1】:

    我曾考虑过类似@Thilo 的回答,但这没有考虑闰年(这似乎出现在您的数据中,因为 365*31=11315,小于 11322)

    您也许可以设计一个复杂的矢量化解决方案,但我很想手动跟踪开始和停止索引:

    NYEARS = 31;
    
    start = 1;
    stop = 365 + isLeapYear(year(1));
    n=1;
    maxValues = nan(NYEARS,1);
    while(n=<NYEARS)
      maxValues(n) = max(data(start:stop,2));
      n=n+1;
      start = stop + 1;
      stop = start + 365 + isLeapYear(year(n));
    end
    

    它可能不是非常快,但我怀疑这也将成为一个瓶颈。

    function leap_p = isLeapYear(year)
      leap_p = ~mod(year,400) || (~mod(year,4) && mod(year,100)) 
    end
    

    【讨论】:

    • 什么是isLeapYear?我的系统无法识别该功能
    • 哦,完全忘记了闰年。好主意!
    • 嗯,不知道那个函数是从哪里来的。这很简单(见编辑)
    • 如果我错了,请纠正我,但我相信您的解决方案需要进行一些更改。 isLeapYear(year(1)) 更容易理解为 isLeapYear(year1) 其中指定了 year1 和 while(n&lt;=NYEARS) 而不是 while(n=&lt;NYEARS)stop = start + 365 + isLeapYear(year(n)); 应该有一个 - 1。最后,我得到一个“索引超出矩阵维度错误”。想法?
    • 1) 当然;这取决于您的数据是什么样的。如果您有一系列年份,那么 year(n) 应该可以工作。否则 (year1 + n - 1) 也可以。 2)是的。那是一个错字。这是
    【解决方案2】:

    更新包括闰年

    我怀疑你拥有的数据量是否重要,但我想我想出了一个解决方案,包括闰年而不使用任何循环。因此,为了完整起见。我们将通过一个小例子再次构建这个想法,闰年有 11 天,而正常年份有 10 天。

    data = 1:103
    isLeapYear = [false, false, true, false, false, true, false, false, true, false]
    

    你应该用 isLeapYear 函数的结果替换所有年份的向量。

    接下来,我们生成一个包含 11 行(或者,在现实生活中是 366 行)和年数列的矩阵,其中仅包含值 1:

    helpmatrix = ones(11, 10)
    

    如果对应年份不是闰年,则将矩阵的最后一行设置为 0:

    helpmatrix(end, ~isLeapYear) = 0
    

    让我们将矩阵写成一个向量(使用如下所述的 reshape)并将所有的相加

    selector = cumsum(reshape(helpmatrix, prod(size(helpmatrix)), 1))
    

    我们可以使用这些值以每年有 11 (366) 天的方式放大原始数据,我们可以使用以下技巧。为了填充第 11 天的值,我们只需重用第 10 天的值,这既不会改变最大值,也不会改变最小值。 (但请注意:其他功能也可能会受此影响!)

    max(reshape(data(selector), 11, length(selector)/11))
    

    要转换它,您只需用 365 和 366 交换所有 10 和 11,并使用 data(selector, 2) 而不是 data(selector) 更改最后一个命令。

    与循环解决方案相比,这可能并没有太大的好处,但它显示了矢量计算的力量。


    老建议

    您可以在更简单的基础上做到这一点。

    reshape 函数允许您将向量(或矩阵,如果需要)转换为另一个行/列布局。

    你的问题可以解决

    max(reshape(data(:,2), 365, length(data)/365))
    

    为了了解发生了什么,我创建了一个较小的示例:

    data = 1:100
    reshape(data, 10, length(data)/10)
    max(reshape(data', 10, length(data')/10))
    

    上面的循环也可以工作,但效率低下。您必须注意如何创建索引。你做i:365*i。在我上面的例子中,这看起来像

    for i=1:10
        i:10*i
    end
    

    这显然不是你想要的。以你能做的正确方式完成

    for i=1:10
        (10*(i-1) + 1):10*i
    end
    

    希望对您有所帮助。

    【讨论】:

    • 这太棒了。有点像数据透视表,但您实际上可以理解发生了什么!谢谢!
    • @Matt Krause 提出了一个关于闰年的好观点。我最终会对输出感到困惑。
    • @Dominik 为了完整起见,我在我的解决方案中添加了一种适应闰年的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    相关资源
    最近更新 更多