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

在R中按分组计算均值的绝对/相对差值及置信区间

Hey Lisa, I’ve got you covered on this problem! Let’s walk through how to calculate those mean differences (absolute and relative) along with their 95% confidence intervals using dplyr, plus a little help from the boot package for robust interval estimates.

Step 1: Set Up Simulated Data

First, let’s replicate a realistic version of your simulated dataset to work with:

library(tidyverse)
library(boot) # For bootstrap confidence intervals

# Simulate data with country-specific trends
set.seed(123)
sim_data <- tibble(
  country = rep(c("USA", "Canada", "UK", "Australia"), each = 50),
  year = rep(2010:2019, each = 20),
  value = rnorm(200, mean = 50, sd = 10) + 
    rep(c(0, 5, 3, -2), each = 50) + # Country base differences
    rep(seq(0, 9, 1), each = 20) # Yearly upward trend
)

Step 2: Filter to Earliest & Latest Years Per Country

We first narrow down the data to only the first and last year for each country to simplify our calculations:

grouped_data <- sim_data %>%
  group_by(country) %>%
  mutate(
    min_year = min(year),
    max_year = max(year)
  ) %>%
  filter(year %in% c(min_year, max_year)) %>%
  ungroup() %>%
  mutate(year_group = ifelse(year == min_year, "early", "late"))

Step 3: Calculate Differences & Bootstrap Confidence Intervals

Bootstrapping is ideal here because it works well for non-normal data and gives robust confidence intervals. Let’s define a function to compute our metrics, then apply it per country:

Define the Bootstrap Statistic Function

# Function to calculate absolute and relative mean differences
calc_diffs <- function(data, indices) {
  sampled_data <- data[indices, ]
  early_mean <- mean(sampled_data$value[sampled_data$year_group == "early"])
  late_mean <- mean(sampled_data$value[sampled_data$year_group == "late"])
  
  abs_diff <- late_mean - early_mean
  rel_diff <- abs_diff / early_mean # Relative difference (% change from early to late)
  
  return(c(abs_diff = abs_diff, rel_diff = rel_diff))
}

Apply Bootstrap Per Country

final_results <- grouped_data %>%
  group_by(country) %>%
  nest() %>% # Package each country's data into a list column
  mutate(
    # Run 1000 bootstrap replicates per country
    boot_output = map(data, ~boot(.x, calc_diffs, R = 1000)),
    # Extract absolute difference and its 95% CI
    abs_diff = map_dbl(boot_output, ~.x$t0["abs_diff"]),
    abs_ci_lower = map_dbl(boot_output, ~boot.ci(.x, type = "perc")$percent[4]),
    abs_ci_upper = map_dbl(boot_output, ~boot.ci(.x, type = "perc")$percent[5]),
    # Extract relative difference and its 95% CI
    rel_diff = map_dbl(boot_output, ~.x$t0["rel_diff"]),
    rel_ci_lower = map_dbl(boot_output, ~boot.ci(.x, type = "perc", index = 2)$percent[4]),
    rel_ci_upper = map_dbl(boot_output, ~boot.ci(.x, type = "perc", index = 2)$percent[5])
  ) %>%
  # Clean up to keep only the metrics we need
  select(country, abs_diff, abs_ci_lower, abs_ci_upper, rel_diff, rel_ci_lower, rel_ci_upper) %>%
  ungroup()

# View the final output
print(final_results)

Step 4: Parametric Alternative (For Normal Data)

If you’re confident your data follows a normal distribution, you can use t.test for the absolute difference CI, and still use bootstrap for the relative difference (since parametric CIs for relative differences are less straightforward):

parametric_results <- grouped_data %>%
  group_by(country) %>%
  summarise(
    early_mean = mean(value[year_group == "early"]),
    late_mean = mean(value[year_group == "late"]),
    abs_diff = late_mean - early_mean,
    # Get t-test CI for absolute difference
    abs_ci = list(t.test(value ~ year_group)$conf.int),
    abs_ci_lower = abs_ci[[1]][1],
    abs_ci_upper = abs_ci[[1]][2],
    # Calculate relative difference
    rel_diff = abs_diff / early_mean,
    # Bootstrap CI for relative difference
    rel_boot = list(boot(cur_data(), function(d, i) {
      e_mean = mean(d$value[d$year_group == "early"][i])
      l_mean = mean(d$value[d$year_group == "late"][i])
      (l_mean - e_mean)/e_mean
    }, R = 1000)),
    rel_ci_lower = boot.ci(rel_boot[[1]], type = "perc")$percent[4],
    rel_ci_upper = boot.ci(rel_boot[[1]], type = "perc")$percent[5]
  ) %>%
  select(-early_mean, -late_mean, -abs_ci, -rel_boot)

Expected Output Format

Here’s what your final results will look like (values will vary slightly based on simulation seed):

# A tibble: 4 × 7
  country   abs_diff abs_ci_lower abs_ci_upper rel_diff rel_ci_lower rel_ci_upper
  <chr>        <dbl>        <dbl>        <dbl>    <dbl>        <dbl>        <dbl>
1 USA           9.28         5.32         13.2    0.180        0.103        0.254
2 Canada        9.47         5.66         13.3    0.172        0.102        0.242
3 UK            9.34         5.51         13.1    0.175        0.104        0.246
4 Australia     9.53         5.71         13.4    0.198        0.118        0.278

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:01:44