我寻找的时候使用一些指导missing,nothing,undef,和NaN在朱莉娅。
例如,对于预先分配数组或从try/返回,所有这些似乎都是合理的选择catch。
ffe*_*tte 20
域名注册地址:
如果您从事统计工作,很可能您想要missing表示集合中缺少特定数据。
如果您想定义一个浮点数数组,但稍后初始化单个元素,undef出于性能原因,您可能需要使用(以避免花费时间将元素设置为一个值,该值将在之后被覆盖):
Vector{Float64}(undef, n)
Run Code Online (Sandbox Code Playgroud)
在相同的情况下,但遵循一种不太注重性能而更注重安全的方法,您还可以将所有元素初始化NaN为 以利用 的传播行为NaN来帮助识别如果您忘记在数组:
fill(NaN, n)
Run Code Online (Sandbox Code Playgroud)您可能会nothing在 Julia 的 API 的某些部分遇到无法计算出有意义的值的情况。但它通常不用于数组中,否则包含数字数据(这似乎是您的用例)
以下是我对这些选项之间差异的看法:
missing用于表示统计意义上的缺失值,即理论上存在但您不知道的值。missing在精神上(在大多数情况下在行为上)与NAR相似。missing值的一个定义特征是您可以在计算中使用它们:
julia> x = 1 # x has a known value: 1
1
julia> y = missing # y has a value, but it is unknown
missing
julia> z = x * y # no error: z has a value, that just happens to be unknown
missing # (as a consequence of not knowing the value of y
Run Code Online (Sandbox Code Playgroud)
的一个重要特征missing是它有自己的特定类型:Missing. 这特别意味着包含missing其他数值中的值的数组在类型上不是同质的:
julia> [1, missing, 3]
3-element Array{Union{Missing, Int64},1}: # not Array{Int64, 1}
1
missing
3
Run Code Online (Sandbox Code Playgroud)
请注意,尽管 Julia 编译器已经非常擅长为如此小的联合处理此类异构数组,但具有不同类型的元素存在固有的性能问题,因为我们无法提前知道元素的类型。
nothing也有自己的类型:Nothing. 相比之下missing,它往往用于没有价值的东西。这就是为什么,与 相比missing,用 计算nothing没有意义,并且会出错:
julia> 3*nothing
ERROR: MethodError: no method matching *(::Int64, ::Nothing)
Run Code Online (Sandbox Code Playgroud)
nothing 主要用作不返回任何内容的函数的返回值,要么是因为它们只有副作用,要么是因为它们无法计算出任何有意义的结果:
julia> @show println("OK") # Only side effects
OK
println("OK") = nothing
julia> @show findfirst('a', "Hello") # No meaningful result
findfirst('a', "Hello") = nothing
Run Code Online (Sandbox Code Playgroud)
另一个值得注意的用途nothing是在函数参数或对象字段中,并不总是为其提供值。这通常在类型系统中表示为 a Union{MeaningfulType, Nothing}。例如,对于二叉树结构的以下定义,叶子(根据定义,它是没有子节点的节点)将表示为子节点为 的节点nothing:
struct TreeNode
child1 :: Union{TreeNode, Nothing}
child2 :: Union{TreeNode, Nothing}
end
leaf = TreeNode(nothing, nothing)
Run Code Online (Sandbox Code Playgroud)
与前两个不同,NaN它没有自己的特定类型:NaN只是类型的特定值Float64(NaN32类似地存在于Float32)。您可能知道,这些值通常作为未定义操作(例如 0/0)的结果出现,并且在浮点算术中具有非常特殊的含义,这使得它们传播(或多或少与missing值相同) . 但除了算术行为之外,这些都是正常的浮点值。特别是,浮点值向量可能包含NaNs 而不会影响其类型:
julia> [1., NaN, 2.]
3-element Array{Float64,1}: # Note how this differs from the example with missing above
1.0
NaN
2.0
Run Code Online (Sandbox Code Playgroud)
undef与迄今为止提到的所有内容都非常不同。它不是真正的值(至少不是具有值的数字),而是一个“标志”,可以传递给数组构造函数以告诉 Julia 不要初始化数组中的值(通常出于性能考虑) )。在下面的例子中,数组元素不会被设置为任何特定的值,但是,由于在 Julia 中没有没有任何值的数字这样的东西,元素将具有任意值(来自内存中向量被分配)。
julia> Vector{Float64}(undef, 3)
3-element Array{Float64,1}:
6.94567437726575e-310
6.94569509953624e-310
6.94567437549977e-310
Run Code Online (Sandbox Code Playgroud)
当元素具有更复杂的类型(技术术语:非 isbits 类型)并且可以区分初始化元素和未初始化元素时,Julia 表示后者为 #undef
julia> mutable struct Foo end
julia> Vector{Foo}(undef, 3)
3-element Array{Foo,1}:
#undef
#undef
#undef
Run Code Online (Sandbox Code Playgroud)
我将总结如下选项。我写的是从“读价值观”的角度,但这也是“写价值观”的指导。
nothing表示“该值不存在”(例如在集合中未找到值时findfirst返回nothing);它是一种单独的类型Nothingmissing意味着“值本身存在但我们不知道它”(我希望通常missing只有在从外部来源获取数据时才能获取数据,例如您有患者数据的记录并且缺少体温(显然它存在 - 只是它没有被记录);我认为 Base 中的任何函数都不能返回它,除了它missing作为参数的情况);它是一种单独的类型MissingNaN-仅仅是一个数值数据(相对于nothing和missing); 如果对数值进行某些操作的结果返回NaN,它会向用户发出信号;根据我的经验,这是NaN应该出现在您的数据中的唯一情况(例如 的结果0/0)undef不是您会看到的值,它仅用于例如Vector{Int}(undef, 10)创建数组而不初始化其值的形式(因此这只是性能优化);仅当您立即想用您计划计算的某些值初始化数组的元素时才应该使用它(如果数组的元素类型不是位类型或位类型的联合,则使用undef将导致#undef条目;对于位undef用于初始化数组的类型只会给你一些垃圾)Those are the standard rules. Now an exception is (and this is a typical practice in some other languages) that sometimes you might want to use NaN for signaling a missing or nothing in a collection. It is not something that is recommended but it has one benefit, which you can see in this example:
julia> x1 = [1.0, NaN]
2-element Array{Float64,1}:
1.0
NaN
julia> x2 = [1.0, missing]
2-element Array{Union{Missing, Float64},1}:
1.0
missing
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,作为NaN浮点值,数组的元素类型x1只是Float64,而在x2数组中,元素类型是Union. 在某些情况下,您可能想要选择x1而不是x2因为执行操作要快missing一些(例如检查可能性有一些最小的开销)。但这是一种通常不应该进行的性能优化,因为其他人在阅读 Julia 代码时通常会看到NaN真正的NaN,而不是发出信号的占位符missing或nothing。
| 归档时间: |
|
| 查看次数: |
675 次 |
| 最近记录: |