拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何处理ifelse函式julia中的缺失值

如何处理ifelse函式julia中的缺失值

白鹭 - 2022-01-25 2094 0 0

我正在使用 Julia,我得到了一个包含 42 个值的资料框,其中 2 个值丢失了。

此值是从 0.23 到 0.3 的价格

我正在尝试获取一个新列,通过ifelse宣告来说明它是便宜还是昂贵

ifelse 应该去:

df.x_category=ifelse.(df.x .< mean(df.x),"cheap", "expensive")

但我收到以下错误:

ERROR: TypeError: non-boolean (Missing) used in boolean context

有没有办法跳过这些缺失值?

我试过:

df.x_category=ifelse.(skipmissing(df.x) .< mean(skipmissing(df.x)),"cheap", "expensive")

但得到这个错误:

ERROR: ArgumentError: New columns must have the same length as old columns

我不能只是洗掉丢失的观察。

我怎样才能做到这一点?

提前致谢!

uj5u.com热心网友回复:

ifelse 只能处理 2 个值,您需要处理 3。假设您有

df = DataFrame(x=rand([0.23,0.3,missing], 10))

mean(df.x)产生 amissing因为一些值是missings。你需要这样做 mean(skipmissing(df.x)))

因此代码可能是:

julia> map(x -> ismissing(x) ? missing : ifelse(x,"cheap", "expensive"), df.x .< mean(skipmissing(df.x)))
10-element Vector{Union{Missing, String}}:
 missing
 missing
 "cheap"
 missing
 "expensive"
 missing
 missing
 missing
 "cheap"
 "cheap"

在这里,我将 ifelse 与map处理缺失值相结合,还有其他方法,但每种方法都需要嵌套一些条件函式。

uj5u.com热心网友回复:

我会用一个回传的函式来做cheapexpensive或者missing

using Statistics
data = ifelse.(rand(Bool,100),missing,100*rand(100)) #generator for the data
meandata = mean(skipmissing(data)) #mean of the data

function category_select(x)
  ismissing(x) && return missing  #short-circuit operator
  return ifelse(x<meandata,"cheap","expensive") #parentheses are optional
end

category_select2(x) = ismissing(x) ? missing : (x < meandata ? "cheap" : "expensive)

#broadcast values
x_category = category_selector.(data)
x_category = category_selector2.(data)

现在,发生了什么?ifelse函式有两件事

  1. 它同时评估两个分支,所以如果一个分支可能出错,它就会出错。拿这个例子:
maybelog(x) = ifelse(x<0,zero(x),log(x)) #ifelse
maybelog2(x) = begin if x<0; zero(x);else;log(x);end #full if expression
maybelog3(x) = x<0 ? zero(x) : log(x) #ternary operator

maybelogx = -1 失败,而maybelog2maybelog3没有。

  1. 第一个自变量总是一个布林值。在您的初始表达式中,结果df.x .< mean(df.x)可以是true,falsemissing,因此ifelse在那里也失败。

在您修改后的表达式中,长度与长度skipmissing(df.x)不同,x因为第一个不计算 x 中存在的缺失值,导致矢量小于资料帧的大小。

uj5u.com热心网友回复:

如果您正在使用 DataFrames.jl(看起来像您这样做),那么我建议您学习简化此类场景语法的元包。以下是使用 DataFrameMacros.jl 撰写查询的方法:

@transform!(df,
            @subset(!ismissing(:x)),
            :x_category = @c ifelse.(:x .< mean(:x), "cheap", "expensive"))

这是我认为最简单的方法。

uj5u.com热心网友回复:

你可以尝试这样的事情。使用玩具资料。

  • 首先将您的字符串值从ifelse矢量中获取。
  • 然后通过将字符串矢量转换为字符串联合并缺失来保存缺失值来准备字符串矢量。
  • 最后将缺失值放入矢量中。
julia> using DataFrames, Random 

julia> vec = ifelse.(df.d[ismissing.(df.d) .== false] .> 0.5,"higher","lower")
40-element Vector{String}:
 "higher"
 "lower"
 "lower"
etc...

julia> vec = convert(Vector{Union{Missing,String}}, vec)
40-element Vector{Union{Missing, String}}

julia> for i in findall(ismissing.(df.d)) insert!(vec, i, missing) end

julia> df.x = vec

julia> df
42×2 DataFrame
 Row │ d                x
     │ Float64?         String?
─────┼──────────────────────────
   10.533183   higher
   20.454029   lower
   30.0176868  lower
   40.172933   lower
   50.958926   higher
   60.973566   higher
   70.30387    lower
   80.176909   lower
   90.956916   higher
  100.584284   higher
  110.937466   higher
  12 │ missing          missing
  130.422956   lower
etc...

资料

julia> Random.seed!(42)
MersenneTwister(42)

julia> data = Random.rand(42)
42-element Vector{Float64}:
 0.5331830160438613
 0.4540291355871424
etc...

julia> data = convert(Vector{Union{Missing,Float64}}, data)
42-element Vector{Union{Missing, Float64}}

julia> data[[12,34]] .= missing
2-element view(::Vector{Union{Missing, Float64}}, [12, 34]) with eltype Union{Missing, Float64}:
 missing
 missing

julia> df = DataFrame(d=data)
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *