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

R中coin::kruskal_test加权秩转换警告问题及替代方案咨询

加权Kruskal-Wallis检验的警告问题与替代方案

我正在使用R中的coin::kruskal_test函数执行加权Kruskal-Wallis检验,但遇到了**“秩转换未考虑权重”**的警告。

触发警告的代码

library(tidyverse)
library(coin)
library(purrr)

set.seed(1)
punteggi = 
  tibble(
    Codice = paste0("cod_", 1:200),
    Regione = sample(c("FVG", "Lazio", "Sicilia"), size = 200, replace = T, prob = c(.4, .2, .4)),
    Genere = sample(c("Femminile", "Maschile"), size = 200, replace = T, prob = c(.6, .4)),
    Area = sample(c("Urbana", "Extra urbana"), size = 200, replace = T, prob = c(.6, .4)),
  )

punteggi = punteggi |> 
  group_by(Regione, Genere, Area) |> 
  mutate(
    mu = runif(1, 4, 7),
    sd = runif(1, 1, 2),
    weight = n()
  ) |> 
  ungroup() |>
  rowwise() |> 
  mutate(pt_tot = rnorm(1, mu, sd))

punteggi

kruskal_per_group_weighted <- function(data) {
  test_result <- tryCatch({
      coin::kruskal_test(pt_tot ~ value, data = data, weights = ~ weight)
  }, error = function(e) {
    message("Errore in kruskal_test: ", e)
    return(NULL)
  })
  return(coin::pvalue(test_result))
}

kruskal_per_group_NO_weighted <- function(data) {
  test_result <- tryCatch({
      coin::kruskal_test(pt_tot ~ value, data = data)
  }, error = function(e) {
    message("Errore in kruskal_test: ", e)
    return(NULL)
  })
  return(coin::pvalue(test_result))
}

punteggi |> 
  pivot_longer(c(Regione, Genere, Area)) |> 
  mutate(across(value, as.factor)) |> 
  nest(.by = name) |> 
  mutate(
    kruskal = map_dbl(data, kruskal_per_group_NO_weighted),
    kruskal_weighted = map_dbl(data, kruskal_per_group_weighted)
    )

收到的警告信息

<warning/rlang_warning>
Warning in `mutate()`:
i In argument: `kruskal_weighted = map_dbl(data, kruskal_per_group_weighted)`.
Caused by warning in `ft()`:
! rank transformation doesn't take weights into account
---
Backtrace:
    x
 1. +-dplyr::mutate(...)
 2. \-dplyr:::mutate.data.frame(...)

问题补充

加权与非加权Kruskal-Wallis检验的p值存在差异。请问是否有方法解决该警告,让coin::kruskal_test的秩转换正确考虑权重?或者在R中执行加权Kruskal-Wallis检验有什么替代方法?


解决方案

1. 理解coin::kruskal_test的权重限制

coin包的kruskal_test函数的weights参数仅用于检验统计量计算阶段的权重调整,不会在秩转换时应用权重,这就是警告的核心原因。当前得到的“加权”结果并非严格意义上的加权Kruskal-Wallis检验。

2. 手动实现加权秩转换

可以先手动计算考虑权重的秩,再用kruskal_test检验:

# 自定义加权秩计算函数(处理结值)
weighted_rank <- function(x, w) {
  order_x <- order(x)
  x_ordered <- x[order_x]
  w_ordered <- w[order_x]
  
  ties <- rle(x_ordered)
  rank_pos <- cumsum(ties$lengths)
  rank_start <- rank_pos - ties$lengths + 1
  
  weighted_ranks <- numeric(length(x))
  for (i in seq_along(ties$values)) {
    idx <- rank_start[i]:rank_pos[i]
    total_w <- sum(w_ordered[idx])
    avg_rank <- sum(w_ordered[idx] * rank_start[i]:rank_pos[i]) / total_w
    weighted_ranks[idx] <- avg_rank
  }
  
  weighted_ranks[order(order_x)] <- weighted_ranks
  return(weighted_ranks)
}

# 修改加权检验函数
kruskal_per_group_weighted_fixed <- function(data) {
  data <- data |>
    mutate(pt_tot_weighted_rank = weighted_rank(pt_tot, weight))
  
  test_result <- tryCatch({
    coin::kruskal_test(pt_tot_weighted_rank ~ value, data = data)
  }, error = function(e) {
    message("Errore in kruskal_test: ", e)
    return(NULL)
  })
  return(coin::pvalue(test_result))
}

# 重新运行检验
punteggi |> 
  pivot_longer(c(Regione, Genere, Area)) |> 
  mutate(across(value, as.factor)) |> 
  nest(.by = name) |> 
  mutate(
    kruskal = map_dbl(data, kruskal_per_group_NO_weighted),
    kruskal_weighted = map_dbl(data, kruskal_per_group_weighted),
    kruskal_weighted_fixed = map_dbl(data, kruskal_per_group_weighted_fixed)
    )

3. 使用替代包:wrs2

wrs2包提供了专门的kruskalwallisW函数,直接支持加权Kruskal-Wallis检验,无需手动处理秩转换:

library(wrs2)

# 修改函数使用wrs2包
kruskal_per_group_weighted_wrs2 <- function(data) {
  test_result <- tryCatch({
    wrs2::kruskalwallisW(pt_tot ~ value, data = data, weights = weight)
  }, error = function(e) {
    message("Errore in kruskalwallisW: ", e)
    return(NULL)
  })
  return(test_result$p.value)
}

# 运行检验
punteggi |> 
  pivot_longer(c(Regione, Genere, Area)) |> 
  mutate(across(value, as.factor)) |> 
  nest(.by = name) |> 
  mutate(
    kruskal = map_dbl(data, kruskal_per_group_NO_weighted),
    kruskal_weighted_wrs2 = map_dbl(data, kruskal_per_group_weighted_wrs2)
    )

4. 注意事项

  • 手动计算加权秩时必须正确处理结值(相同观测值),否则会影响结果准确性;
  • wrs2包的实现经过验证,是更简便可靠的选择。

内容的提问来源于stack exchange,提问作者Erik De Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:07:38