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

如何用select对DataFrame指定列批量应用频率编码?

通用频率编码解决方案(适配任意数量分类/数值列)

我来帮你搞定这个通用频率编码的问题!你的原始实现确实在列数多的时候不太好用,这里有个更通用、高效的解决方案,完美解决你提到的三个问题:

核心思路

先批量计算所有分类列的频率映射字典,再批量替换原分类列,同时自动保留所有非分类列(不管是Int、Complex还是其他数值类型)。

完整代码实现

using DataFrames

# 你的示例数据
df = DataFrame(categ = ["a", "a", "a", "b"], numer = [1, 2, 3, 4])

# 1. 自动识别所有分类列(这里以字符串类型为例,可按需调整)
cat_cols = names(df, eltype -> eltype <: AbstractString)

# 2. 批量计算每个分类列的频率映射字典
freq_maps = Dict()
for col in cat_cols
    # 按列分组统计出现次数
    freq_df = combine(groupby(df, col), nrow => :count)
    # 计算频率(出现次数 / 总行数)
    freq_df[!, :freq] = freq_df.count ./ size(df, 1)
    # 生成"分类值 => 频率"的字典
    freq_maps[col] = Dict(zip(freq_df[!, col], freq_df.freq))
end

# 3. 批量替换分类列,自动保留所有非分类列
result_df = transform(df, [col => ByRow(x -> freq_maps[col][x]) => col for col in cat_cols])

运行后得到的result_df就是你预期的结果:

4×2 DataFrame
 Row │ categ    numer
     │ Float64  Int64
─────┼────────────────
   1 │    0.75      1
   2 │    0.75      2
   3 │    0.75      3
   4 │    0.25      4

针对你提到的问题的解决细节

  1. 适配任意数量分类列:
    通过names(df, eltype -> eltype <: AbstractString)自动筛选所有字符串类型的列作为分类列,哪怕你有上百个分类列,也不需要手动一一指定。如果你的分类列是CategoricalValue类型,只需要把筛选条件改成eltype -> eltype <: CategoricalValue即可。

  2. 避免硬编码列名:
    预先为每个分类列单独计算频率字典,替换时直接调用对应列的字典,不再依赖硬编码的df.categ,完全适配多分类列场景。

  3. 自动保留所有非分类列:
    transform函数默认会保留DataFrame的所有原有列,我们只对需要处理的分类列进行替换,其他列(不管是Int64、Complex还是其他数值类型)都会自动保留,再也不用手动指定要保留的列。

扩展优化(更简洁的写法)

如果喜欢更紧凑的代码,可以把频率字典的计算写成一行(可读性稍弱,但功能一致):

freq_maps = Dict(
    col => Dict(zip(gdf[!, col], gdf.freq)) 
    for col in cat_cols 
    let gdf = combine(groupby(df, col), nrow => :count)
        gdf[!, :freq] = gdf.count ./ size(df, 1)
        gdf
    end
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:36:10