julia - Julia:DataFrame 的类型稳定性
问题描述
如何以类型稳定的方式访问 DataFrame 的列?
假设我有以下数据:
df = DataFrame(x = fill(1.0, 1000000), y = fill(1, 1000000), z = fill("1", 1000000))
现在我想做一些递归计算(所以我不能使用transform
)
function foo!(df::DataFrame)
for i in 1:nrow(df)
if (i > 1) df.x[i] += df.x[i-1] end
end
end
这有可怕的表现:
julia> @time foo!(df)
0.144921 seconds (6.00 M allocations: 91.529 MiB)
此简化示例中的快速修复如下:
function bar!(df::DataFrame)
x::Vector{Float64} = df.x
for i in length(x)
if (i > 1) x[i] += x[i-1] end
end
end
julia> @time bar!(df)
0.000004 seconds
但是,我正在寻找一个通用的解决方案,例如当递归计算只是指定为一个函数时
function foo2!(df::DataFrame, fn::Function)
for i in 1:nrow(df)
if (i > 1) fn(df, i) end
end
end
function my_fn(df::DataFrame, i::Int64)
x::Vector{Float64} = df.x
x[i] += x[i-1]
end
虽然这(几乎)没有分配,但它仍然很慢。
julia> @time foo2!(df, my_fn)
0.050465 seconds (1 allocation: 16 bytes)
是否有一种高性能的方法并允许这种灵活性/通用性?
编辑:我还应该提到,在实践中,不知道函数fn
依赖于哪些列。即我正在寻找一种方法,允许高性能访问/更新内部的任意列fn
。fn
如果需要,可以将所需的列与例如一起指定Vector{Symbol}
。
编辑2:我尝试使用如下屏障功能,但它不是高性能的
function foo3!(df::DataFrame, fn::Function, colnames::Vector{Symbol})
cols = map(cname -> df[!,cname], colnames)
for i in 1:nrow(df)
if (i > 1) fn(cols..., i) end
end
end
function my_fn1(x::Vector{Float64}, i::Int64)
x[i] += x[i-1]
end
function my_fn2(x::Vector{Float64}, y::Vector{Int64}, i::Int64)
x[i] += x[i-1] * y[i-1]
end
@time foo3!(df, my_fn1, [:x])
@time foo3!(df, my_fn2, [:x, :y])
解决方案
此问题旨在(避免对宽数据帧进行过度编译),如何处理它的方法在https://github.com/bkamins/Julia-DataFrames-Tutorial/blob/master/11_performance.ipynb中进行了说明。
一般来说,您应该减少索引到数据框的次数。所以在这种情况下做:
julia> function foo3!(x::AbstractVector, fn::Function)
for i in 2:length(x)
fn(x, i)
end
end
foo3! (generic function with 1 method)
julia> function my_fn(x::AbstractVector, i::Int64)
x[i] += x[i-1]
end
my_fn (generic function with 1 method)
julia> @time foo3!(df.x, my_fn)
0.010746 seconds (16.60 k allocations: 926.036 KiB)
julia> @time foo3!(df.x, my_fn)
0.002301 seconds
(我正在使用您想要传递自定义函数的版本)
推荐阅读
- java - 如何在图像加载之前显示进度条。?
- json - Wordpress Headless 使用 wp-api 进行 reactJS
- python - 如何找到使用的缩减算法?
- python - 如何在运行时使用运行时参数在 python(如 shell 脚本)中使用 -- 在运行时调用方法
- node.js - 按日期分割数据的最佳方法是什么
- tensorflow - 如何在 TensorFlow 中加载最后一个检查点?
- documentation - 如何为调用图中的函数设置颜色?
- c - 检查数组是否是C中的对角占优矩阵
- python-3.x - 读取包含逗号的 .csv
- r - 计算R中四个不同列的最大时间