什么是通过列或行操作的惯用Julia样式?

时间:2013-12-24 15:29:30

标签: r julia

道歉,如果这相当普遍 - 虽然仍然是一个编码问题。

我手上有点时间,我一直在努力学习Julia。我认为一个好的开始是复制R microbenchmark函数 - 所以我可以无缝地比较R和Julia函数。

e.g。对于我试图模拟的2个R函数,这是microbenchmark输出:

Unit: seconds
expr                    min        lq    median        uq        max      neval
vectorised(x, y)    0.2058464 0.2165744 0.2610062 0.2612965  0.2805144     5
devectorised(x, y)  9.7923054 9.8095265 9.8097871 9.8606076 10.0144012     5

到目前为止,在朱莉娅,我正在尝试编写惯用语和希望可理解/简洁的代码。因此,我用列表推导替换了一个双循环来创建一个时序数组,如下所示:

function timer(fs::Vector{Function}, reps::Integer)
#    funs=length(fs)
#    times = Array(Float64, reps, funs)
#    for funsitr in 1:funs
#        for repsitr in 1:reps
#            times[reps, funs] = @elapsed fs[funs]()
#        end
#    end

    times= [@elapsed fs[funs]() for   x=1:reps, funs=1:length(fs)]
    return times
end

这为两个函数中的每一个提供了一系列时序:

julia> test=timer([vec, devec], 10)
10x2 Array{Float64,2}:
 0.231621  0.173984
 0.237173  0.210059
 0.26722   0.174007
 0.265869  0.208332
 0.266447  0.174051
 0.266637  0.208457
 0.267824  0.174044
 0.26576   0.208687
 0.267089  0.174014
 0.266926  0.208741

我的问题(最后)是我如何惯用在一个或多个行的列(或行)中应用minmaxmedian等函数数组没有使用循环?

我当然可以轻松地完成这个带循环的简单案例(我在上面划掉的sim) - 但我在文档中找不到等同于apply(array,1, fun)或甚至{{ {1}}。

我能想到的最接近的通用功能是

colMeans

..但语法确实没有吸引力。在Julia中,对于多维数组的列或行,有更自然的julia> [mean(test[:,col]) for col=1:size(test)[2]] 2-element Array{Any,1}: 0.231621 0.237173 函数方法吗?

3 个答案:

答案 0 :(得分:13)

您想要的功能是mapslices

答案 1 :(得分:11)

julia中的匿名函数 目前缓慢,因此除非您对匿名函数进行基准测试,否则我不会将它们用于基准测试。这将为在代码的性能关键部分中不使用匿名函数的代码提供错误的性能预测。

我认为你想要减少函数的两个参数版本,比如sum(arr,1)来总结第一个维度。如果没有可用的库函数,您可以使用reducedim

答案 2 :(得分:4)

我认为@ivarne有正确的答案(并勾选了它)但我只是补充说我做了apply之类的功能:

function aaply(fun::Function, dim::Integer, ar::Array)
            if !(1 <= dim <= 2)
                    error("rows is 1, columns is 2")
            end
            if(dim==1)
                res= [fun(ar[row, :]) for row=1:size(ar)[dim]]
            end
            if(dim==2)
                res= [fun(ar[:,col]) for col=1:size(ar)[dim]]
            end
            return res
end

然后得到我想要的东西:

julia> aaply(quantile, 2, test)
2-element Array{Any,1}:
 [0.231621,0.265787,0.266542,0.267048,0.267824]
 [0.173984,0.174021,0.191191,0.20863,0.210059] 

其中quantile是一个内置的,它给出min,lq,median,uq和max ..就像microbenchmark一样。

编辑按照这里的建议,我测试了新功能mapslice,其功能与R apply非常相似,并针对上述功能进行了基准测试。请注意,mapslice列为dim=1,而test[:,1]是第一列...所以与R相反,尽管它具有相同的索引?

# nonsense test data big columns
julia> ar=ones(Int64,1000000,4)
1000000x4 Array{Int64,2}:

# built in function
julia> ms()=mapslices(quantile,ar,1)
ms (generic function with 1 method)

# my apply function
julia> aa()=aaply(quantile, 2, ar)
aa (generic function with 1 method)

# compare both functions
julia> aaply(quantile, 2, timer1([ms, aa], 40))
2-element Array{Any,1}:
 [0.23566,0.236108,0.236348,0.236735,0.243008] 
 [0.235401,0.236058,0.236257,0.236686,0.238958]

因此,乐趣大致相同。通过阅读Julia邮件列表中的一些内容,他们似乎打算在这个Julialang上做一些工作,以便通过引用制作切片而不是制作每个切片的新副本(列行等)...