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

R语言如何按period、source分组计算数据框各值的百分位数

问题说明

现有如下测试数据框:

library(tibble)
library(dplyr)

test <- tibble(
  period = c(
    '2019_q1','2019_q1','2019_q1','2019_q1','2019_q1',
    '2019_q2','2019_q2','2019_q2','2019_q2','2019_q2',
    '2019_q2','2019_q2','2019_q2'
  ),
  company = c(
    'google','facebook','amazon','ebay','wikipedia',
    'google','youtube','amazon','wikipedia','yelp',
    'yahoo','tide','target'
  ),
  source = c(
    rep('website',5), rep('phone',8)
  ),
  values = c(10,20,30,50,90,6,12,45,52,80,92,8,17)
)

需求为同时按period和source两列分组,计算组内每个values对应的百分位数。

运行如下代码时触发报错:

test %>%    
    group_by(period, source) %>%     
    arrange(period, source) %>%    
    filter(!is.na(values)) %>%    
    mutate(percentile = quantile(values, probs = seq(0,1,0.25)))

报错信息:

Error in mutate(): ! Problem while computing percentile =
quantile(values, probs = seq(0, 1, 0.25)). x percentile must be size
1, not 5. i The error occurred in group 1: period = "2019_q1",
source = "website".

第一组(2019_q1 + website)的期望输出如下:

periodcompanyvaluespercentile
2019_q1google1025
2019_q1facebook2025
2019_q1amazon3050
2019_q1ebay5050
2019_q1wikipedia9075

报错原因

quantile(values, probs = seq(0,1,0.25))会固定返回长度为5的分位点临界值(对应0%、25%、50%、75%、100%分位的阈值),但mutate()要求新生成列的长度必须和当前分组的行数完全一致:示例中第一组有5行、第二组有8行,直接传入长度为5的向量必然触发长度不匹配错误。


解决代码

要实现每个值对应百分位的计算,不要直接调用quantile()生成分位点阈值,用组内排名映射的方式实现即可,两种常用写法:

  • 用dplyr内置的percent_rank()做百分位排名,适配四分位分箱需求,代码最简洁:
test %>%    
  group_by(period, source) %>%     
  filter(!is.na(values)) %>%  
  arrange(values, .by_group = TRUE) %>%  
  mutate(
    percentile = ceiling(percent_rank(values) * 4) * 25
  ) %>%
  ungroup()
  • 如果需要严格匹配quantile()的分位点计算规则,用findInterval()做区间匹配,逻辑更可控:
test %>%    
  group_by(period, source) %>%     
  filter(!is.na(values)) %>%    
  arrange(values, .by_group = TRUE) %>%    
  mutate(
    q = list(quantile(values, probs = seq(0, 1, 0.25))),
    percentile = findInterval(values, q[[1]], left.open = TRUE) * 25
  ) %>%
  select(-q) %>%
  ungroup()

两段代码运行后,第一组的输出和期望效果完全一致。


内容的提问来源于stack exchange,提问作者Beans On Toast

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:24:21