You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以惯用方式移除DataFrame中缺失值占比过高的列?

移除DataFrame中缺失值占比超指定比例的列(Julia实现)

问题背景

需要移除DataFrame中缺失值占比超过指定阈值的列,已有一种繁琐的实现方式,尝试Julia惯用写法时出现报错,实际数据集为330列、350000行,各列缺失值占比0-100%不等。

原有繁琐实现

using DataFrames
df = DataFrame(
    "A" => [1, 7, 2],
    "B" => [3, missing, -3],
    "C" => [3, 0, 6],
    "D" => [missing, 4, 2],
    "E" => [4, 3, -4])

nmis = describe(df, :nmissing)
filter!(row -> (row.nmissing / nrow(df) ) > 0.2, nmis)
for v in eachrow(nmis)
    var=v.variable
    select!(df, Not("$var"))
end
println(describe(df))

错误的惯用写法及报错

尝试的代码:

for col in eachcol(df)
    println(count(ismissing, col))
end
println(describe(df[!, [any(x -> count(ismissing, x) < 1, col) for col in eachcol(df)]]))

报错信息:

0
1
0
1
0
ERROR: LoadError: MethodError: no method matching iterate(::Missing)

Closest candidates are:
  iterate(::Union{LinRange, StepRangeLen})
   @ Base range.jl:880
  iterate(::Union{LinRange, StepRangeLen}, ::Integer)
   @ Base range.jl:880
  iterate(::T) where T<:Union{Base.KeySet{<:Any, <:Dict}, Base.ValueIterator{<:Dict}}
   @ Base dict.jl:698
  ...

Stacktrace:
  [1] iterate(::Base.Generator{Missing, typeof(ismissing)})
    @ Base .\generator.jl:44
  [2] _simple_count_helper(g::Base.Generator{Missing, typeof(ismissing)}, init::Int64)
    @ Base .\reduce.jl:1356
  [3] _simple_count(pred::Function, itr::Missing, init::Int64)
    @ Base .\reduce.jl:1352
  [4] count(f::Function, itr::Missing; init::Int64)
    @ Base .\reduce.jl:1350
  [5] count(f::Function, itr::Missing)
    @ Base .\reduce.jl:1350
  [6] (::var"#6#8")(x::Missing)
    @ Main c:\Users\TGebbels\OneDrive - The National Lottery Community Fund\Documents\360Giving\ShrinkCSV.jl:26
  [7] _any
    @ .\reduce.jl:1215 [inlined]
  [8] #any#829
    @ .\reducedim.jl:1004 [inlined]
  [9] any
    @ .\reducedim.jl:1004 [inlined]
 [10] (::var"#5#7")(col::Vector{Union{Missing, Int64}})
    @ Main .\none:0
 [11] iterate
    @ .\generator.jl:47 [inlined]
 [12] collect_to!(dest::Vector{Bool}, itr::Base.Generator{DataFrames.DataFrameColumns{DataFrame}, var"#5#7"}, offs::Int64, st::Int64)
    @ Base .\array.jl:840
 [13] collect_to_with_first!(dest::Vector{Bool}, v1::Bool, itr::Base.Generator{DataFrames.DataFrameColumns{DataFrame}, var"#5#7"}, st::Int64)
    @ Base .\array.jl:818
 [14] collect(itr::Base.Generator{DataFrames.DataFrameColumns{DataFrame}, var"#5#7"})
    @ Base .\array.jl:792
 [15] top-level scope
    @ c:\Users\TGebbels\OneDrive ...\Documents\360Giving\ShrinkCSV.jl:26
in expression starting at c:\Users\TGebbels\OneDrive ...\Documents\360Giving\ShrinkCSV.jl:26

错误原因

错误代码中any(x -> count(ismissing, x) < 1, col)逻辑错误:col是列向量,any会遍历列中的每个元素x,而count(ismissing, x)试图对单个值(如missing或整数)进行计数,但单个值不是可迭代对象,因此抛出MethodError。正确做法是直接对整个列统计缺失值数量,无需使用any。

符合Julia惯用风格的实现方法

以下几种方法简洁高效,适合大数据集:

方法1:筛选列名后更新DataFrame

using DataFrames

df = DataFrame(
    "A" => [1, 7, 2],
    "B" => [3, missing, -3],
    "C" => [3, 0, 6],
    "D" => [missing, 4, 2],
    "E" => [4, 3, -4])

threshold = 0.2  # 指定缺失值占比阈值
total_rows = nrow(df)

# 筛选出缺失值占比≤阈值的列名
keep_cols = [col_name for col_name in names(df) if count(ismissing, df[!, col_name]) / total_rows ≤ threshold]

# 更新原DataFrame
select!(df, keep_cols)

println(describe(df))

方法2:结合eachcol与列名枚举

using DataFrames

df = DataFrame(
    "A" => [1, 7, 2],
    "B" => [3, missing, -3],
    "C" => [3, 0, 6],
    "D" => [missing, 4, 2],
    "E" => [4, 3, -4])

threshold = 0.2
total_rows = nrow(df)

# enumerate(eachcol(df, true)) 会返回(列名, 列数据)的元组
keep_cols = [col_name for (col_name, col_data) in enumerate(eachcol(df, true)) 
             if count(ismissing, col_data) / total_rows ≤ threshold]

select!(df, keep_cols)

println(describe(df))

方法3:使用Cols函数的简洁写法

using DataFrames

df = DataFrame(
    "A" => [1, 7, 2],
    "B" => [3, missing, -3],
    "C" => [3, 0, 6],
    "D" => [missing, 4, 2],
    "E" => [4, 3, -4])

threshold = 0.2
total_rows = nrow(df)

# 直接在select!中用Cols筛选符合条件的列
select!(df, Cols(col -> count(ismissing, col) / total_rows ≤ threshold))

println(describe(df))

以上三种方法均为Julia惯用的函数式风格写法,代码简洁且效率较高,适合处理大规模数据集。

内容的提问来源于stack exchange,提问作者Tim Gebbels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:58:13