在Julia 1中将缺失值转换为数值

时间:2018-08-31 14:39:15

标签: dataframe julia

我正在尝试将df中所有缺少的值转换为数字值,例如0(是的,知道我在做什么。)。

在Julia 0.6中,我可以写:

julia> df = DataFrame(
              cat = ["green","blue","white"],
              v1   = [1.0,missing,2.0],
              v2   = [1,2,missing]
            )
julia> [df[ismissing.(df[i]), i] = 0 for i in names(df)]

并获得:

julia> df
3×3 DataFrames.DataFrame
│ Row │ cat   │ v1  │ v2 │
├─────┼───────┼─────┼────┤
│ 1   │ green │ 1.0 │ 1  │
│ 2   │ blue  │ 0.0 │ 2  │
│ 3   │ white │ 2.0 │ 0  │

如果我在Julia 0.7中尝试过,则会收到一个非常奇怪的错误:

  

MethodError:无法convert类型为Float64的对象为对象   类型为String

我无法转换为字符串?有任何解释(和解决方法)吗?

2 个答案:

答案 0 :(得分:2)

此问题的原因是,广播机制已在Julia 0.6和Julia 1.0之间更改(并且已在DataFrames.jl的insert_multiple_entries!函数中使用)。最后,fill!被调用,它会在检查集合是否为空之前尝试进行转换。

实际上,如果您想就位进行完全通用的替换 (据我了解,您想这样做),这比Base中的操作复杂且效率较低(原因是您无法依赖检查向量中元素的类型,例如您可以将Int分配给Float64的向量,并且它们具有不同的类型):

function myreplacemissing!(vec, val)
    for i in eachindex(vec)
        ismissing(vec[i]) && (vec[i] = val)
    end
end

现在您可以开始:

foreach(col -> myreplacemissing!(col[2], 0), eachcol(df))

答案 1 :(得分:1)

虽然我很欣赏Bogumil Kaminski的回答(也因为现在我已经理解了失败的原因),但是如果它的解决方案恰好在非数字列中存在缺失元素,那么它提出的解决方案也会失败,例如:

df = DataFrame(
  cat = ["green","blue",missing],
  v1   = [1.0,missing,2.0],
  v2   = [1,2,missing]
)

我可以做的是使用(根据我的需要选择一个或仅一个):

[df[ismissing.(df[i]), i] = 0 for i in names(df) if  typeintersect(Number, eltype(df[i])) != Union{}]
[df[ismissing.(df[i]), i] = "" for i in names(df) if  typeintersect(String, eltype(df[i])) != Union{}]

优点是我可以为不同类型的列选择所需的值类型,以“丢失替换”(例如,数字为0或字符串为“”)。

编辑:

也许更具可读性,再次感谢Begumil's answer

[df[ismissing.(df[i]), i] = 0 for i in names(df) if  Base.nonmissingtype(eltype(df[i])) <: Number]
[df[ismissing.(df[i]), i] = "" for i in names(df) if  Base.nonmissingtype(eltype(df[i])) <: String]