(使用Julia)如何通过对同一小时内的值求平均值来减少数据矩阵?

时间:2018-07-16 04:22:08

标签: matrix timestamp julia mean sample

我正在尝试减小数据的大小,但无法使其正常工作。我有1个月内每分钟获取的数据点。我想减少此数据以每小时获取一个样本。问题是:我的某些运行具有“ NA”值,因此我删除了这些行。每小时不是完全有60分-它会有所不同。

我有一个“时间戳”列。如果数据集具有相同的日期和时间,则我使用它来创建一个具有相同值的“ datehour”列。我想平均所有具有相同“ datehour”值的值。

我该怎么做?我已经尝试过使用下面的if和for循环,但是运行起来却花了很长时间。

感谢您的帮助!我是Julia的新手,来自Matlab背景。

========代码=========

uniquedatehour=unique(datehour,1)

index=[]
avedata=reshape([],0,length(alldata[1,:]))

for j in uniquedatehour
    for i in 1:length(datehour)

        if datehour[i]==j
            index=vcat(index,i)
        else
            rows=alldata[index,:]
            rows=convert(Array{Float64,2},rows)
            avehour=mean(rows,1)
            avedata=vcat(avedata,avehour)
            index=[]
            continue
        end
    end 
end

1 个答案:

答案 0 :(得分:0)

有多层可以优化此代码。我假设您的数据在datehour上排序(您的代码假设是这样)。

第一层:一般推荐

将代码包装在一个函数中。在Julia中全局范围内执行代码比在函数中慢得多。通过包装,请确保将数据作为参数传递给函数,或者如果数据在全局范围内,则应使用const;

第二层:对算法的建议

  1. 类似[]的语句创建的类型为Any的数组很慢,您应该使用类似index=Int[]的类型限定符来使其快速;
  2. vcat那样使用index=vcat(index,i)效率低下,最好就地执行push!(index, i)
  3. 最好预先分配avedata,例如fill(NA, length(uniquedatehour), size(alldata, 2))并为现有矩阵分配值,而不是对其进行vcat
  4. 如果我没有记错的话,您的代码将产生错误的结果,因为它不会捕获uniquedatehour向量的最后一项(假设它只有一个元素并检查会发生什么-avedata将有零行)
  5. 可能根本不需要rows=convert(Array{Float64,2},rows)行。如果alldata不是Matrix{Float64},则最好以Matrix{Float64}(alldata)开始进行转换;
  6. 您可以将行rows=alldata[index,:]更改为view(alldata, index, :)之类的视图以避免分配;
  7. 通常,您可以避免创建index向量,因为只要记住相同值范围的开始s和结束e位置,然后使用范围{{ 1}}中选择所需的行。

如果您更正了这些问题,请发布您的更新代码,也许仍有待改进,但我需要进一步的帮助,但是需要一些不同的算法方法(但为简单起见,您可能会喜欢以下选项)。

第三层:我会怎么做

我将使用s:e包来解决此问题,如下所示:

DataFrames

这不是最快的解决方案(因为它可以转换为using DataFrames df = DataFrame(alldata) # assuming alldata is Matrix{Float64}, otherwise convert it here df[:grouping] = datehour agg = aggregate(df, :grouping, mean) # maybe this is all what you need if DataFrame is OK for you Matrix(agg[2:end]) # here is how you can convert DataFrame back to a matrix 并返回,但对我来说要简单得多)。