【问题标题】:Merge large number of arrays by common column values in julia通过 julia 中的公共列值合并大量数组
【发布时间】:2018-06-21 04:27:08
【问题描述】:

扩展我之前在这里提出的上一个问题,假设我们有大量数组(比如 500 个数组),例如以下 3 个第一个

5.0 3.5 6.0 3.6 7.0 3.0

5.0 4.5 6.0 4.7 8.0 3.0

5.0 4.0 6.0 3.2 8.0 4.0

以此类推,存储在一个数组中,这样我们就有了一个包含 500 个上述类型数组的数组。我想通过第一列的公共值将 500 个数组合并为一个数组,计算第二列相应元素的平均值。结果必须是以下数组:

5.0 mean of all 5's values 6.0 mean of all 6's values 7.0 mean of all 7's values 8.0 mean of all 8's values

我怎样才能做到这一点?谢谢!

【问题讨论】:

    标签: julia array-merge


    【解决方案1】:

    还回来了,对https://stackoverflow.com/a/50842721/2001017稍作修改

    function aggregate(m::Array{<:Array{<:Number,2},1})
    
        result=sortrows(vcat(m...))
    
        n = size(result,1)
        if n <= 1
            return result
        end 
    
        key_idx = 1
        key     = result[key_idx,1]
        count   = 1
    
        for i in 2:n
          if key == result[i,1]
              result[key_idx,2:end] += result[i,2:end]
              count                 += 1
          else
              result[key_idx,2:end] /= count
              count                  = 1
              key                    = result[i,1]
              key_idx               += 1
              result[key_idx,1]      = key 
              result[key_idx,2:end]  = result[i,2:end]
          end
        end
    
        result[key_idx,2:end] /= count
    
        return result[1:key_idx,:]
    end   
    

    演示:

    x = [5.0  3.5
         6.0  3.6
         7.0  3.0]
    
    y = [5.0  4.5
         6.0  4.7
         8.0  3.0]
    
    z = [5.0  4.0
         6.0  3.2
         8.0  4.0]
    
    a=[x,y,z]
    

    julia> a
    3-element Array{Array{Float64,2},1}:
     [5.0 3.5; 6.0 3.6; 7.0 3.0]
     [5.0 4.5; 6.0 4.7; 8.0 3.0]
     [5.0 4.0; 6.0 3.2; 8.0 4.0]
    

    julia> aggregate(a)
    4×2 Array{Float64,2}:
     5.0  4.0    
     6.0  3.83333
     7.0  3.0    
     8.0  3.5
    

    【讨论】:

    • 是的!我想到了关于我上一篇文章的这个扩展。谢谢!
    【解决方案2】:

    这是一个比@PicaudVincent 的答案快约 6 倍的版本(基于他的输入数据),但它不对键进行排序,因此返回矩阵的行是任意顺序的:

    function accumarrays(A::Vector{Matrix{T}}) where {T}
        d = Dict{T, Tuple{T, Int}}()
        for a in A
            for i in indices(a, 1)
                ai = a[i, 1]
                d[ai] = get(d, ai, (zero(T), 0)) .+ (a[i, 2], 1)
            end
        end
        Aout = Matrix{typeof(one(T)/1)}(length(d), 2)
        i = 0
        for (key, val) in d
            Aout[i+=1, 1] = key
            Aout[i, 2] = val[1] / val[2]
        end
        return Aout
    end
    

    如果您需要对行进行排序,这可行,但速度仅快 4-5 倍:

    function accumarrays_(A::Vector{Matrix{T}}) where {T}
        d = Dict{T, Tuple{T, Int}}()
        for a in A
            for i in indices(a, 1)
                ai = a[i, 1]
                d[ai] = get(d, ai, (zero(T), 0)) .+ (a[i, 2], 1)
            end
        end
        dkeys = sort!(collect(keys(d)))
        Aout = Matrix{typeof(one(T)/1)}(length(dkeys), 2)
        for i in eachindex(dkeys)
            val = d[dkeys[i]]
            Aout[i, 1] = dkeys[i]
            Aout[i, 2] = val[1] / val[2]
        end
        return Aout
    end
    

    【讨论】:

    • 非常感谢!速度确实总是受欢迎的,我正在寻找什么!
    • 如果我们想获得标准差呢?我尝试使用函数std(..., corrected=false) 调整以d[ai]= get... 开头的行,但我无法获得标准偏差而不是平均值。即使是平均值,也不能使用mean 函数吗?
    • 这行不通。 stdmean 函数必须处理数字集合,但我的函数所做的是专门避免构建集合,因此这些函数无法操作。 可能做一些类似于我为获得标准所做的事情。然后你需要保持 squared 数字的运行总和以及运行总和和计数。最后,您可以从那里计算标准。
    • 对。最好是使用标准差的定义。我将尝试修改计算总和的行。
    猜你喜欢
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 2018-10-31
    • 2020-10-15
    • 1970-01-01
    • 2014-10-10
    相关资源
    最近更新 更多