编写用于在 Julia 中传递 GroupedDataFrame 的函数方法
Writing function methods for passing GroupedDataFrame in Julia
我写了一个像下面这样的函数:
gini(v::Array{<:Real,1}) = (2 * sum([x*i for (i,x) in enumerate(sort(v))]) / sum(sort(v)) - (length(v)+1))/(length(v))
此函数在传递 Vector
或 DataFrame
时效果很好。例如:
gini(collect(1:1:10))
# 0.3
或
using DataFrames # DataFrames v1.3.2
df = DataFrame(v = collect(1:1:10),
group = repeat([1, 2], 5))
combine(df, :v => gini)
#1×1 DataFrame
# Row │ v_gini
# │ Float64
#─────┼─────────
# 1 │ 0.3
但是,与其他将向量作为参数的函数(例如 Statistics.mean
)不同,它在传递 GroupedDataFrame
时抛出 MethodError
。
combine(groupby(df, :group), :v => gini)
# nested task error: MethodError: no method matching #gini(::SubArray{Int64, 1, Vector{Int64}, Tuple{SubArray{Int64, 1, #Vector{Int64}, Tuple{UnitRange{Int64}}, true}}, false})
# Closest candidates are:
# gini(::Vector{<:Real})
如何编写在传递 GroupedDataFrame
时可以正常工作的函数?
您需要将方法签名更改为:
gini(v::AbstractVector{<:Real})
关键是 combine
传递了向量的视图(它没有 Vector
类型,但 SubArray
)。因此,您需要通过函数允许任何向量,而不仅仅是 Vector
.
我写了一个像下面这样的函数:
gini(v::Array{<:Real,1}) = (2 * sum([x*i for (i,x) in enumerate(sort(v))]) / sum(sort(v)) - (length(v)+1))/(length(v))
此函数在传递 Vector
或 DataFrame
时效果很好。例如:
gini(collect(1:1:10))
# 0.3
或
using DataFrames # DataFrames v1.3.2
df = DataFrame(v = collect(1:1:10),
group = repeat([1, 2], 5))
combine(df, :v => gini)
#1×1 DataFrame
# Row │ v_gini
# │ Float64
#─────┼─────────
# 1 │ 0.3
但是,与其他将向量作为参数的函数(例如 Statistics.mean
)不同,它在传递 GroupedDataFrame
时抛出 MethodError
。
combine(groupby(df, :group), :v => gini)
# nested task error: MethodError: no method matching #gini(::SubArray{Int64, 1, Vector{Int64}, Tuple{SubArray{Int64, 1, #Vector{Int64}, Tuple{UnitRange{Int64}}, true}}, false})
# Closest candidates are:
# gini(::Vector{<:Real})
如何编写在传递 GroupedDataFrame
时可以正常工作的函数?
您需要将方法签名更改为:
gini(v::AbstractVector{<:Real})
关键是 combine
传递了向量的视图(它没有 Vector
类型,但 SubArray
)。因此,您需要通过函数允许任何向量,而不仅仅是 Vector
.