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

如何实现满足最小计数阈值的整数数据非均匀分箱(隐私保护)

整数型数据非均匀分箱实现(最小频数阈值约束)

需求说明

出于隐私保护目的,需对整数型数值数据进行非均匀分箱处理:

  • 每个分箱的频数不得低于最小阈值x
  • 尽可能最小化箱宽,减少数据损失

需要实现一个函数,输入整数集合(如data$column)与最小计数阈值x,返回包含分箱结果的treated_column字段。

示例(阈值x=3)

set.seed(10)
data <- tibble(column = sample(1:5, 10, replace = TRUE))
# 原数据频数统计
data %>% count(column)

# 预期分箱结果
expected_data <- data %>% mutate(treated_column = c('3-5','1-2','1-2','3-5','3-5','1-2','1-2','1-2','3-5','3-5'))
expected_data %>% count(treated_column)

贴近实际的测试数据

set.seed(5)
data <- tibble(columnA = sample(1:100, 1000, replace = TRUE),
               columnB = sample(10:1000, 1000, replace = TRUE))

实现方案

以下是基于梳理的逻辑实现的R函数,依赖dplyr和tibble包:

library(dplyr)
library(tibble)

bin_integer_data <- function(data_col, x) {
  # 统计频数并按整数升序排列
  freq_table <- data_col %>%
    enframe(name = NULL, value = "value") %>%
    count(value, sort = FALSE) %>%
    arrange(value)
  
  if(nrow(freq_table) == 0) {
    stop("输入数据为空")
  }
  
  bins <- list()
  current_bin_start <- freq_table$value[1]
  current_count <- freq_table$n[1]
  
  # 遍历合并分箱,直到满足阈值要求
  for(i in 2:nrow(freq_table)) {
    if(current_count < x) {
      current_count <- current_count + freq_table$n[i]
    } else {
      bins <- append(bins, list(c(current_bin_start, freq_table$value[i-1])))
      current_bin_start <- freq_table$value[i]
      current_count <- freq_table$n[i]
    }
  }
  
  # 添加最后一个临时分箱
  bins <- append(bins, list(c(current_bin_start, freq_table$value[nrow(freq_table)])))
  
  # 检查最后一个分箱的频数,不足则合并最后两个分箱
  if(length(bins) >= 2) {
    last_bin_vals <- freq_table %>%
      filter(value >= bins[[length(bins)]][1], value <= bins[[length(bins)]][2]) %>%
      pull(n) %>%
      sum()
    
    if(last_bin_vals < x) {
      merged_bin <- c(bins[[length(bins)-1]][1], bins[[length(bins)]][2])
      bins <- bins[-c(length(bins)-1, length(bins))]
      bins <- append(bins, list(merged_bin))
    }
  }
  
  # 生成分箱标签与原数值的映射表
  bin_mapping <- tibble(
    value = integer(),
    treated_column = character()
  )
  
  for(bin in bins) {
    start <- bin[1]
    end <- bin[2]
    label <- if(start == end) as.character(start) else paste0(start, "-", end)
    bin_mapping <- bind_rows(
      bin_mapping,
      tibble(value = start:end, treated_column = label)
    )
  }
  
  # 将原数据映射为分箱结果
  treated_col <- data_col %>%
    enframe(name = NULL, value = "value") %>%
    left_join(bin_mapping, by = "value") %>%
    pull(treated_column)
  
  return(treated_col)
}

使用示例

# 测试基础示例
set.seed(10)
data <- tibble(column = sample(1:5, 10, replace = TRUE))
data$treated_column <- bin_integer_data(data$column, 3)
data %>% count(treated_column)

# 测试实际数据
set.seed(5)
data <- tibble(columnA = sample(1:100, 1000, replace = TRUE),
               columnB = sample(10:1000, 1000, replace = TRUE))
data$treated_columnA <- bin_integer_data(data$columnA, 20)
data$treated_columnB <- bin_integer_data(data$columnB, 15)

# 查看分箱结果
data %>% count(treated_columnA)
data %>% count(treated_columnB)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 03:37:51