缺失值
缺失值的传播
当传递给标准数学运算符和函数时,缺失值会自动传播。 对于这些函数,其中一个操作数的值的不确定性导致结果的不确定性。 在实践中,这意味着使用缺失值的数学运算符通常返回’missing'。:
julia> missing + 1
missing
julia> "a" * missing
missing
julia> abs(missing)
missing
由于’missing’是一个常规Julia对象,因此此分发规则仅适用于已明确同意实现此行为的函数。 这可以通过以下方式实现:
-
通过添加为`Missing`类型的参数定义的特定方法;
-
通过获取此类型的参数并将其传递给传播它们的函数(例如,标准数学运算符)。 包应该考虑在定义新函数时分发缺失值是否有意义,如果是这样,则相应地定义方法。 将missing(
missing
)值传递给没有接受`Missing`类型输出参数的方法的函数 'MethodError'与任何其他类型完全相同。
可以通过将它们包装在包提供的`passmissing`函数中来使不分配缺失值的函数这样做。 https://github.com/JuliaData/Missings.jl [错过。jl]。 例如’f(x)`变为’f(f)(x)'。
相等和比较运算符
标准相等和比较运算符遵循上述分布规则:如果缺少任何操作数,则缺少结果。 以下是一些例子:
julia> missing == 1
missing
julia> missing == missing
missing
julia> missing < 1
missing
julia> 2 >= missing
missing
特别要注意的是,missing==missing’返回’missing
,所以`=='不能用来检查值是否缺失。 要检查`x`是否丢失,请使用 'ismissing(x)'。
特殊比较运算符 'isequal'和 ==='
是分发规则的例外。 它们将始终返回值’Bool,即使存在缺失值,将`missing`视为等于`missing’并且与其他任何值不同。 因此,它们可用于检查值是否缺失(`missing')。:
julia> missing === 1
false
julia> isequal(missing, 1)
false
julia> missing === missing
true
julia> isequal(missing, missing)
true
julia> isless(1, missing)
true
julia> isless(missing, Inf)
false
julia> isless(missing, missing)
false
逻辑运算符
逻辑(或布尔)运算符 |
, `&'和 'xor'是另一种特殊情况,因为它们仅在逻辑上需要时传播缺失值。 对于这些运算符,结果是否未定义取决于具体的操作。 这遵循牢固确立的规则。 https://en.wikipedia.org/wiki/Three-valued_logic [three-digit logic],它们被实现,例如,SQL中的’NULL’和R中的’NA'。这种抽象表示对应于相对自然的行为,最好通过具体的例子来解释。
让我们用逻辑运算符"or"来说明这个原理。 |
. 遵循布尔逻辑的规则,如果其中一个操作数具有值’true`,则另一个操作数的值不会影响结果,该结果将始终为`true'。:
julia> true | true
true
julia> true | false
true
julia> false | true
true
根据这个观察,我们可以得出结论,如果其中一个操作数具有值`true`而另一个具有值`missing`,我们知道结果是`true`,尽管其中一个操作数的实际值存在不确定性。 如果我们可以观察第二个操作数的实际值,它的可能值可能是"true"或"false",在这两种情况下,结果都是"true"。 因此,在该特定情况下,不存在__值不适用。:
julia> true | missing
true
julia> missing | true
true
相反,如果其中一个操作数的值为"false",则结果可以是"true"或"false",具体取决于另一个操作数的值。 因此,如果操作数具有值’missing`,则结果也必须具有值`missing'。:
julia> false | true
true
julia> true | false
true
julia> false | false
false
julia> false | missing
missing
julia> missing | false
missing
逻辑运算符的行为"和" '&'类似于运算符`|`的行为,不同之处在于当其中一个操作数具有值`false’时,没有值不适用。 例如,如果第一个操作数是这种情况:
julia> false & false
false
julia> false & true
false
julia> false & missing
false
另一方面,当其中一个操作数具有值`true’时,则传播值的缺失,例如,第一个:
julia> true & true
true
julia> true & false
false
julia> true & missing
missing
执行的顺序和根据缩写方案的计算运算符
执行顺序运算符,包括 '如果', while'
和 三元运算符'x? y:z,不允许缺失值。 这是由于如果我们可以观察到实际值是"真"还是"假"的不确定性。 这意味着我们不知道程序应该如何表现。 在这种情况下,发出 'TypeError',只要在此上下文中遇到值’missing`:
julia> if missing
println("here")
end
ERROR: TypeError: non-boolean (Missing) used in boolean context
出于同样的原因,与上面介绍的逻辑运算符不同,逻辑运算符是使用缩写方案计算的。 '&&'和[ |
)在操作数的值决定是否评估下一个操作数的情况下,不允许缺少值。 例如: |
julia> missing || false
ERROR: TypeError: non-boolean (Missing) used in boolean context
julia> missing && false
ERROR: TypeError: non-boolean (Missing) used in boolean context
julia> true && missing && false
ERROR: TypeError: non-boolean (Missing) used in boolean context
相反,当可以在没有缺失值的情况下确定结果时,不会返回错误。 当代码在计算缺失(missing
)操作数之前根据缩短的方案使用计算并且当缺失(missing
)操作数是最后一个时,情况就是这样。:
julia> true && missing
missing
朱莉娅>假&&失踪
错误
具有缺失值的数组
您可以创建包含缺失值的数组,就像其他数组一样。:
julia> [1, missing]
2-element Vector{Union{Missing, Int64}}:
1
missing
如本例所示,此类数组的元素类型为’Union{Missing, T}`,类型为`T’缺失值。 这反映了这个数组中的条目可以是类型`T`(这里是`Int64`)或类型`Missing’的事实。 这种类型的数组使用类似于`Array'的高效内存存储。{T},其中包含与'Array组合的实际值{UInt8}
,表示记录的类型(即是缺失(Missing
)还是`T`)。
允许缺失值的数组可以使用标准语法构造。 使用’数组{Union{Missing, T}}(missing,dims)'创建填充有缺失值的数组:
julia> Array{Union{Missing, String}}(missing, 2, 3)
2×3 Matrix{Union{Missing, String}}:
missing missing missing
missing missing missing
使用`undef`或`similar’目前可能会产生一个填充有`missing`值的数组,但这不是获得这样一个数组的正确方法。 请改用`missing`构造函数,如上所示。 |
具有允许缺失条目的元素类型的数组(例如,'Vector{Union{Missing, T}不包含缺失条目的}`)可以转换为不允许缺失条目的数组类型(例如,'+Vector{T}+)使用 '转换'。 如果数组包含值’missing
,则在转换期间发出’MethodError`:
julia> x = Union{Missing, String}["a", "b"]
2-element Vector{Union{Missing, String}}:
"a"
"b"
julia> convert(Array{String}, x)
2-element Vector{String}:
"a"
"b"
julia> y = Union{Missing, String}[missing, "b"]
2-element Vector{Union{Missing, String}}:
missing
"b"
julia> convert(Array{String}, y)
ERROR: MethodError: Cannot `convert` an object of type Missing to an object of type String
跳过缺失值
由于缺失值是使用标准数学运算符传播的,因此当调用包含缺失值的数组时,减少函数返回"缺失"。:
julia> sum([1, missing])
missing
在这种情况下,使用函数 `skipmissing'跳过缺失值:
julia> sum(skipmissing([1, missing]))
1
此辅助函数返回有效过滤缺失值的迭代器。 因此,它可以与任何支持迭代器的函数一起使用。:
julia> x = skipmissing([3, missing, 2, 1])
skipmissing(Union{Missing, Int64}[3, missing, 2, 1])
julia> maximum(x)
3
julia> sum(x)
6
julia> mapreduce(sqrt, +, x)
4.146264369941973
通过在数组上调用’skipmissing’创建的对象可以使用父数组中的索引进行索引。 与缺失值对应的索引对于这些值无效,并且在尝试使用它们时返回错误(它们也跳过’keys’和’eachindex'):
julia> x[1]
3
julia> x[2]
ERROR: MissingException: the value at index (2,) is missing
[...]
这允许使用索引的函数与"skipmissing"结合使用。 这在很大程度上是搜索和查找功能的情况。 这些函数返回’skipmissing’返回的对象允许的索引,以及父数组中匹配条目的索引。_:
julia> findall(==(1), x)
1-element Vector{Int64}:
4
julia> findfirst(!iszero, x)
1
julia> argmax(x)
1
使用方法 `collect'提取非缺失值并将其存储在数组中:
julia> collect(x)
3-element Vector{Int64}:
3
2
1
具有数组的逻辑运算
上面描述的逻辑运算符的三位逻辑也被应用于数组的逻辑函数所使用。 因此,使用运算符检查数组的相等性 ==在不知道丢失记录的实际值的情况下无法确定结果的所有情况下返回`missing`。 实际上,这意味着如果比较数组的所有非缺失值相等,但其中一个或两个数组包含缺失值(可能位于不同位置),则返回’missing`:
julia> [1, missing] == [2, missing]
false
julia> [1, missing] == [1, missing]
missing
julia> [1, 2, missing] == [1, missing, 2]
missing
至于个别值,使用 isequal
将缺失(missing')值视为与其他缺失(`missing
)值相等,但与非缺失值不同:
julia> isequal([1, missing], [1, missing])
true
julia> isequal([1, 2, missing], [1, missing, 2])
false
julia> all([true, missing])
missing
julia> all([false, missing])
false
julia> any([true, missing])
true
julia> any([false, missing])
missing