【问题标题】:Convert missing to a numerical value in Julia 1在 Julia 1 中将缺失转换为数值
【发布时间】:2018-09-03 16:21:52
【问题描述】:

我正在尝试将 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 类型的对象到一个对象 字符串类型

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

【问题讨论】:

  • 如果我删除了 cat 列它可以工作.. 它似乎仍在尝试应用分配,即使 cat 的情况下的数组是空的,而在 Julia 0.6 中它让我们说“更聪明”,意识到在哪里操作的集合是空的..
  • 在列表理解中添加if typeof(df[i]) <: Vector{Union{Missing, Number}} 不起作用。如果我能找到一种方法来指定联合内的类型(请参阅the separate SO question 我确实打开了)我可以解决问题!

标签: dataframe julia


【解决方案1】:

这个问题的原因是 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))

【讨论】:

    【解决方案2】:

    虽然我很欣赏 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]
    

    【讨论】:

      猜你喜欢
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2018-09-21
      相关资源
      最近更新 更多