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

优化R代码:基于Interval分箱高效计算两变量均值

R语言高效分组分箱计算均值优化方案

我是R语言新手,一直在想办法优化代码提升效率。我的需求是:针对每个受试者,把30个Interval划分为6个各含5个区间的分箱,计算每个分箱内XDistance和YDistance的均值并生成新表。目前靠重复代码实现了,但尝试用for循环或lapply优化失败,求高效方案。

数据子集

mydata <- structure(list(Subject = c("1", "1", "1", "1", "1", "1", "1", 
"1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", 
"1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "2", "2", "2", 
"2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", 
"2", "2", "2", "2"), Interval = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 1L, 2L, 3L, 
4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 
18L, 19L, 20L), XDistance = c(240, 252.5, 125, 107.5, 170, 77.5, 
105, 157.5, 187.5, 125, 62.5, 187.5, 15, 130, 45, 0, 80, 205, 
97.5, 85, 160, 152.5, 12.5, 107.5, 157.5, 112.5, 102.5, 82.5, 
55, 57.5, 217.5, 235, 142.5, 215, 127.5, 120, 115, 167.5, 182.5, 
147.5, 207.5, 90, 165, 155, 222.5, 140, 175, 72.5, 112.5, 172.5
), YDistance = c(235, 190, 145, 132.5, 210, 92.5, 160, 150, 192.5, 
170, 105, 162.5, 87.5, 170, 80, 12.5, 145, 182.5, 170, 87.5, 
102.5, 122.5, 0, 117.5, 247.5, 195, 145, 167.5, 97.5, 75, 395, 
277.5, 245, 260, 270, 237.5, 235, 275, 245, 210, 200, 92.5, 217.5, 
195, 225, 247.5, 212.5, 135, 187.5, 192.5)), row.names = c(NA, 
-50L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x0000022000ea9850>)

当前使用的繁琐代码

mydata <- read.csv("DSR_Practice.csv")
par(mfrow = c(2,2))
library(dplyr)
mydata <- mydata[!(mydata$Subject == "Not Used"), ]

library(data.table)
setDT(mydata)
cuts <- list(c(1,5), c(6,10), c(11,15), c(16, 20), c(21, 25), c(26, 30))
data <- lapply(X = cuts, function(i) {
  mydata[between(x = mydata[ , Interval], lower = i[1], upper = i[2])]
})
Bin1 <- as.data.frame(data[[1]])
Bin1 <- Bin1 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()
Bin2 <- as.data.frame(data[[2]])
Bin2 <- Bin2 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()
Bin3 <- as.data.frame(data[[3]])
Bin3 <- Bin3 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()
Bin4 <- as.data.frame(data[[4]])
Bin4 <- Bin4 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()
Bin5 <- as.data.frame(data[[5]])
Bin5 <- Bin5 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()
Bin6 <- as.data.frame(data[[6]])
Bin6 <- Bin6 %>%
  group_by(Subject) %>%
  summarise(across(XDistance:YDistance, mean, X = "{XDistance}.{mean}", Y = "{YDistance}. {mean}")) %>%
  as.data.frame()


df.list <- list(Bin1, Bin2, Bin3, Bin4, Bin5, Bin6)
df.list <- Reduce(function(x, y) merge(x, y, all = TRUE), df.list)

优化方案

方法1:使用dplyr一步完成分箱与计算

核心思路是先给每个Interval分配对应的分箱编号,再按受试者+分箱分组计算均值,最后转成目标宽表格式:

library(dplyr)
library(tidyr)

# 读取数据并预处理
mydata <- read.csv("DSR_Practice.csv")
mydata <- mydata[!(mydata$Subject == "Not Used"), ]

# 自动分箱、计算均值并转宽表
result <- mydata %>%
  group_by(Subject) %>%
  mutate(Bin = paste0("Bin", ceiling(Interval / 5))) %>%
  group_by(Subject, Bin) %>%
  summarise(across(XDistance:YDistance, mean, .names = "{.col}_mean")) %>%
  pivot_wider(names_from = Bin, values_from = c(XDistance_mean, YDistance_mean)) %>%
  ungroup()

print(result)

方法2:使用data.table高效处理

如果数据量较大,data.table的速度优势更明显,同样通过自动分箱、分组计算完成需求:

library(data.table)

# 读取数据并转成data.table格式
mydata <- fread("DSR_Practice.csv")
mydata <- mydata[Subject != "Not Used"]

# 分箱、计算均值、转宽表
mydata[, Bin := paste0("Bin", ceiling(Interval / 5)), by = Subject]
result <- mydata[, lapply(.SD, mean), by = .(Subject, Bin), .SDcols = c("XDistance", "YDistance")]
result <- dcast(result, Subject ~ Bin, value.var = c("XDistance", "YDistance"))

print(result)

以上两种方法均避免了重复代码,直接一步完成分箱、均值计算与格式转换,效率和可读性远高于原有写法。

内容的提问来源于stack exchange,提问作者Miguel De Leon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:41:26