我正在寻找一种方法将数据框分成相同大小的组(每组中的行数基本相同),其组的平均值几乎相等。
User Data
1 5.0
2 4.5
3 3.5
4 6.0
5 7.0
6 6.5
7 5.5
8 6.2
9 5.7
10 5.9
这与this request非常相似但是这只会将数据分成两组。
我的实际数据集包含75-150行,我需要将它分成5-10组相等的平均值和相当相等的大小。
我研究过Google&堆栈交换最近几天,我只是没有太多运气。任何指导都会很棒。
提前致谢!
更多详情:
也许我需要提供更多细节,下面我已经包含了一个真实的数据集。我们是一家运输公司,这个数据集有Driver ID,Miles,Gallons提供。我一直在做的是将数据读入R,并添加和MPG列如下:
data <- read.csv('filename')
data$MPG <- data$Miles / data$Gallons
然后我尝试了下面提供的两个答案。 Arun的想法给了我几乎相同的组大小(每组9个成员,10组),但是平均值的变化很大,从6.615到7.093,这对我来说太大了。托马斯的想法变化有点紧张,但团体规模与6-13名成员不同。
我们希望做的是改进车队MPG,我们将通过基于团队的比赛来实现这一目标,所以我需要随机地将球队与他们一起从相对同一组MPG开始。
也许这有帮助,可以引导我们朝着正确的方向前进?我尝试用我的编程语言做这个,但它每次都锁定计算机,所以我认为R可能能够更好地处理数据。
再次感谢!
答案 0 :(得分:3)
如果类似的方法确实非常重要,我将下面的模拟放在一起,基本上看一组特定组大小的数据(n
)的不同组合(k
)然后最小化组均值的方差。通过该最小化,您可以从模拟结果中提取该分组。
df <- data.frame(User=1:1000,Data=rnorm(1000,0,1)) # example data
myfun = function(){
k <- 5 # number of groups
tmp <- seq(length(mpg))%%ngroups # really efficient code from @qwwqwwq's answer
thisgroup <- sample(tmp, dim(df)[1], FALSE) # pull a sample
# thisgroup <- sample(1:k,dim(df)[1],TRUE) # original version
thisavg <- as.vector(by(df$Data, thisgroup, mean)) # group means
thisvar <- var(thisavg) # variance of means
return(list(group=thisgroup, avgs=thisavg, var=thisvar))
}
n <- 1000 # number of simulations
sorts <- replicate(n, myfun(), simplify=FALSE)
wh <- which.min(sapply(sorts, function(x) x$var)) # minimization
# sorts[[wh]] # this is the sample you want
split(df, sorts[[wh]]$group) # list of separate dataframes for each group
如果您不关心每组中有多少个案例,只需将k
行移动到该函数中并使其成为随机抽取,您也可以拥有不同大小的k <- 5
从您愿意拥有的群体数量范围。
但是,可能还有其他方法可以做到这一点。
答案 1 :(得分:3)
按照托马斯的想法,这是一种蛮力/贪婪的方法,它会给出或多或少相同的值(你可以选择更多的重复,直到你同意解决方案的接近程度)。
# Assuming the data you provided is in `df`
grp <- 5
myfun <- function() {
samp <- sample(nrow(df))
s.mean <- tapply(df$Data, samp %% grp, mean)
s.var <- var(s.mean)
list(samp, s.mean, s.var)
}
out <- replicate(1000, myfun(), simplify=FALSE)
min.pos <- which.min(sapply(out, `[[`, 3))
min.idx <- out[[min.pos]][[1]]
split(df$Data[min.idx], min.idx %% grp)
$`0`
[1] 7.0 5.9
$`1`
[1] 5.0 6.5
$`2`
[1] 5.5 4.5
$`3`
[1] 6.2 3.5
$`4`
[1] 5.7 6.0
这就是out[min.pos]
的样子:
out[min.pos]
[[1]]
[[1]][[1]]
[1] 7 9 8 5 3 4 1 2 10 6
[[1]][[2]]
0 1 2 3 4
5.85 5.70 5.60 5.25 5.50
[[1]][[3]]
[1] 0.05075
答案 2 :(得分:1)
我能想到的最简单的方法:对数据进行排序,按照组的数量对所有指标进行模数化,然后完成。如果数据是正常分布的,我认为应该可以正常工作。具有尽可能相同大小的群体的优势。
mpg <- rnorm(150)
mpg <- sort(mpg)
ngroups = 13
df = data.frame( mpg=mpg, group=seq(length(mpg))%%ngroups)
tapply(df$mpg, df$group, mean)
0 1 2 3 4 5 6 7 8
0.080400272 -0.110797283 -0.046698548 -0.014177675 0.024410834 0.048370962 0.066265303 0.087119914 -0.062259638
9 10 11 12
-0.042172496 -0.003451581 0.033853024 0.056947458