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

问题描述 投票:1回答:2

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

在朱莉娅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:不能将类型为Float64的对象convert转换为String类型的对象

我无法得到我想要转换为字符串???任何解释(和解决方法)?

dataframe julia
2个回答
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
投票

虽然我很欣赏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]
© www.soinside.com 2019 - 2024. All rights reserved.