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

如何在使用ntile()对堆叠数据按类别分5组时排除首尾10%数据并标记为NA

这是个很实用的需求!我们可以通过先界定每个类别需要排除的首尾10%数据范围,再对中间数据单独计算分位数分组的方式实现,同时保留所有原始数据并标记对应分组。下面给你两种不同思路的实现方案,你可以根据实际需求选择:

方案1:基于数值分位数排除首尾10%

这种方法是通过计算每个类别数值的10%和90%分位数,把落在分位数之外的数据标记为NA,中间区间的数据再分5组:

library(tidyverse)

# 生成示例数据(用pivot_longer替代melt,更符合tidyverse语法)
set.seed(123) # 设置随机种子保证结果可复现
r1 <- rnorm(10, 0, 1)
r2 <- rnorm(10, 2, 4)
df <- cbind(r1, r2) %>% 
  as.data.frame() %>% 
  pivot_longer(cols = everything(), names_to = "Var2", values_to = "value")

# 处理分组
df_processed <- df %>%
  group_by(Var2) %>%
  mutate(
    # 计算每个组的10%和90%分位数(可通过type参数调整分位数计算规则)
    p10 = quantile(value, 0.1, type = 1),
    p90 = quantile(value, 0.9, type = 1),
    # 标记是否属于中间80%的数据
    is_mid = value > p10 & value < p90,
    # 对中间数据计算分位数分组,首尾数据设为NA
    group = case_when(
      !is_mid ~ NA_integer_,
      # 提取中间数据计算ntile,再通过match映射回原数据位置
      TRUE ~ ntile(value[is_mid], 5)[match(value, value[is_mid])]
    )
  ) %>%
  select(-p10, -p90, -is_mid) # 移除临时辅助列

# 查看结果
print(df_processed)

关键逻辑说明:

  • quantile()的type参数可以调整分位数的计算方式(默认是type=7),你可以根据业务需求选择合适的规则
  • match(value, value[is_mid])用来保证中间数据的分组结果能正确对应到原数据的位置,避免顺序混乱

方案2:基于数据数量比例排除首尾10%

如果你的需求是严格排除每个类别中数量占比10%的首尾数据(比如每组10条数据就各排除1条),而不是基于数值分位数,可以用排序后的位置来界定:

df_processed <- df %>%
  group_by(Var2) %>%
  mutate(
    total = n(),
    # 对每个组的数值排序,得到位次
    value_rank = row_number(value),
    # 计算首尾需要排除的数量(用floor取整,也可以用ceiling根据需求调整)
    exclude_bottom = floor(total * 0.1),
    exclude_top = floor(total * 0.1),
    # 分配分组
    group = case_when(
      # 首尾部分标记为NA
      value_rank <= exclude_bottom | value_rank > total - exclude_top ~ NA_integer_,
      # 中间部分计算ntile分组
      TRUE ~ ntile(value[value_rank > exclude_bottom & value_rank <= total - exclude_top], 5)[match(value_rank, value_rank[value_rank > exclude_bottom & value_rank <= total - exclude_top])]
    )
  ) %>%
  select(-total, -value_rank, -exclude_bottom, -exclude_top) # 移除临时列

关键逻辑说明:

  • row_number(value)会对每个组的数值从小到大排序,生成位次
  • floor(total*0.1)保证按数量比例排除,比如10条数据排除1条,25条数据排除2条(25*10%=2.5,floor后是2)

两种方案都能满足你的需求,核心都是通过分组计算筛选条件,再结合case_when和ntile实现分组标记,同时保留所有原始数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 13:44:07