我正在尝试将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
我无法转换为字符串?有任何解释(和解决方法)吗?
答案 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]