【问题标题】:Julia: creating a method for Any vector with missing valuesJulia:为任何缺少值的向量创建一个方法
【发布时间】:2018-08-21 13:50:17
【问题描述】:

我想创建一个处理缺失值的函数。但是,当我尝试指定缺少的类型 Array{Missing, 1} 时,它会出错。

function f(x::Array{<:Number, 1})
    # do something complicated
    println("no missings.")
    println(sum(x))
end

function f(x::Array{Missing, 1})
    x = collect(skipmissing(x))
    # do something complicated
    println("removed missings.")
    f(x)
end

f([2, 3, 5])
f([2, 3, 5, missing])

我知道我的类型不是 Missing 而是 Array{Union{Missing, Int64},1}

当我指定此类型时,它适用于上述情况。但是,我想使用所有类型(字符串、浮点数等,不仅是 Int64)。

我试过了

function f(x::Array{Missing, 1})
    ...
end

但它又出错了……这么说

f (generic function with 1 method)
ERROR: LoadError: MethodError: no method matching f(::Array{Union{Missing, Int64},1})
Closest candidates are:
  f(::Array{Any,1}) at ...

我怎么能说我希望类型与任何东西都成为联合缺失?


编辑(重新制定)

让我们有这 4 个向量和两个处理字符串和数字的函数。

x1 = [1, 2, 3]
x2 = [1, 2, 3, missing]
x3 = ["1", "2", "3"]
x4 = ["1", "2", "3", missing]


function f(x::Array{<:Number,1})
    println(sum(x))
end
function f(x::Array{String,1})
    println(join(x))
end

f(x) 不适用于 x2 和 x3,因为它们的类型分别为 Array{Union{Missing, Int64},1}Array{Union{Missing, String},1}

可以只有一个函数来检测向量是否包含缺失,删除它们,然后适当地处理它。

例如:

function f(x::Array{Any, 1})
    x = collect(skipmissing(x))
    print("removed missings")
    f(x)
end

但这不起作用,因为Any 表示混合类型(例如,字符串和数字),并不表示字符串或数字或其他任何内容。


编辑 2 部分修复

这行得通:

function f(x::Array)
    x = collect(skipmissing(x))
    print("removed missings")
    f(x)
end

[但是,那么,如何指定数组的形状(维数)...? (虽然这可能是一个无关的话题)]

【问题讨论】:

    标签: function methods julia missing-data dispatch


    【解决方案1】:

    您可以通过以下方式进行:

    function f(x::Vector{<:Number})
        # do something complicated
        println("no missings.")
        println(sum(x))
    end
    
    function f(x::Vector{Union{Missing,T}}) where {T<:Number}
        x = collect(skipmissing(x))
        # do something complicated
        println("removed missings.")
        f(x)
    end
    

    现在它可以工作了:

    julia> f([2, 3, 5])
    no missings.
    10
    
    julia> f([2, 3, 5, missing])
    removed missings.
    no missings.
    10
    

    编辑:

    我将尝试回答提出的问题(如果我遗漏了什么,请添加评论)。

    第一个Vector{Union{Missing, &lt;:Number}}Vector{Union{Missing, Number}} 相同,因为tibL 表示为Vector{Union{Missing, &lt;:Number}} 的范围规则转换为Array{Union{Missing, T} where T&lt;:Number,1},而where 子句位于Array 内。

    第二(这里我不确定这是否是你想要的)。我了解您想要以下行为:

    julia> g(x::Array{>:Missing,1}) = "$(eltype(x)) allows missing"
    g (generic function with 2 methods)
    
    julia> g(x::Array{T,1}) where T = "$(eltype(x)) does not allow missing"
    g (generic function with 2 methods)
    
    julia> g([1,2,3])
    "Int64 does not allow missing"
    
    julia> g([1,2,missing])
    "Union{Missing, Int64} allows missing"
    
    julia> g(["a",'a'])
    "Any allows missing"
    
    julia> g(Union{String,Char}["a",'a'])
    "Union{Char, String} does not allow missing"
    

    请注意最后两行 - 尽管 ["a", 'a'] 不包含缺失,但数组具有 Any 元素类型,因此它可能包含缺失。最后一种情况排除了它。

    您还可以看到,您可以将Array{T,N} 的第二个参数更改为其他参数以获得不同的维度。

    此示例也有效,因为第一种方法更具体地捕获所有允许Missing 的情况,而第二种方法更一般地捕获剩余的情况(即本质上不允许Missing 的情况)。

    【讨论】:

    • 确实如此,但是如果您尝试写 f(x::Vector{Union{Missing, &lt;:Number}}) 它不会,我相信这是 OP 不清楚的地方?
    • 太棒了!但如何也包括 String 类型? (假设第一个函数不返回 sum 但与字符串兼容的任何其他内容)。我试过where{T&lt;:Any],但也失败了……@tibL 提出了一个很好的观点
    • @DominiqueMakowski Any 类型还包括 Missing 类型,因此您可以编写一个采用 Vector{Any} 的函数(不需要联合)
    • (继续我的第一条评论discourse.julialang.org/t/union-of-missing-and-number/13834),foo(x::Vector{Union{Missing, T}}) where T&lt;:Numberfoo(x::Vector{Union{Missing, T} where T&lt;:Number}) 之间的类型范围有所不同
    • 我真的点击了这个问题,想“嗯,我想知道 Bogumił 是如何回答这个问题的”xD
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    相关资源
    最近更新 更多