Преобразование отсутствует в числовое значение в Юлии 1 - PullRequest
0 голосов
/ 31 августа 2018

Я пытаюсь преобразовать все пропущенные значения в 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: Невозможно convert объект типа Float64 для объекта типа String

Я не могу получить то, что пытаюсь преобразовать в строку ??? Любое объяснение (и обходной путь)?

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Хотя я ценю ответ Богумила Камински (также потому, что теперь я понял причины неудачи), его предлагаемое решение дает сбой, если в нем есть пропущенные элементы в нечисловых столбцах, например ::

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 для числа или "" для строки).

EDIT:

Возможно, более читабельно, спасибо еще раз Ответ Бегумила :

[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]
0 голосов
/ 31 августа 2018

Причина этой проблемы заключается в том, что механизм вещания изменился между Julia 0.6 и Julia 1.0 (и он используется в функции insert_multiple_entries! в DataFrames.jl). В конце вызывается 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))
...