如何在Julia 1.0中使用数组中的NaN替换Inf值?

时间:2018-11-24 23:49:47

标签: julia

我已经在几个地方在线看到了解决方案

 a = [1 2 3; 4 5 Inf]
 a[isinf(a)] = NaN

但这给我关于Julia 1.0.1的错误:

 ERROR: MethodError: no method matching isinf(::Array{Float64,2})
 Closest candidates are:
   isinf(::BigFloat) at mpfr.jl:851
   isinf(::Missing) at missing.jl:79
   isinf(::ForwardDiff.Dual) at <path on my local machine>

有什么作用?

3 个答案:

答案 0 :(得分:8)

作为附加评论。执行此操作的标准功能是replace!。您可以像这样使用它:

julia>  a = [1 2 3; 4 5 Inf]
2×3 Array{Float64,2}:
 1.0  2.0    3.0
 4.0  5.0  Inf

julia> replace!(a, Inf=>NaN)
2×3 Array{Float64,2}:
 1.0  2.0    3.0
 4.0  5.0  NaN

对于大型阵列,它的性能要优于广播。

如果您确实需要速度,可以编写一个简单的函数,如下所示:

function inf2nan(x)
    for i in eachindex(x)
        @inbounds x[i] = ifelse(isinf(x[i]), NaN, x[i])
    end
end

现在让我们简单地比较三个选项的性能:

julia> function bench()
           x = fill(Inf, 10^8)
           @time x[isinf.(x)] .= NaN
           x = fill(Inf, 10^8)
           @time replace!(x, Inf=>NaN)
           x = fill(Inf, 10^8)
           @time inf2nan(x)
       end
bench (generic function with 1 method)

julia> bench()
  0.980434 seconds (9 allocations: 774.865 MiB, 0.16% gc time)
  0.183578 seconds
  0.109929 seconds

julia> bench()
  0.971408 seconds (9 allocations: 774.865 MiB, 0.03% gc time)
  0.184163 seconds
  0.102161 seconds

答案 1 :(得分:3)

编辑:有关解决此问题的最佳方法,请参见@BogumilKaminski的出色回答。这个答案解决了一个更普遍的问题,为什么isinf和相关函数不再在数组上起作用。

您遇到了一个更普遍的问题,即在v1.0之前的版本中,许多对数组起作用的功能不再在v1.0中的数组上起作用,因为您应该使用广播。 v1.0的正确解决方案是:

a[isinf.(a)] .= NaN

我实际上是在两个地方播音。首先,我们在数组isinf上广播a,但是我们也在NaN上将RHS上的标量.=广播到LHS数组上的所有索引位置。总的来说,点广播表示法非常灵活且性能卓越,是Julia的最新迭代中我最喜欢的功能之一。

答案 2 :(得分:0)

您正在将整个数组传递给isinf,它不适用于数组,适用于数字。试试这个:

[isinf(i) ? NaN : i for i in a]