将数据拆分为具有相同均值的组

时间:2013-07-05 21:37:09

标签: r

我正在寻找一种方法将数据框分成相同大小的组(每组中的行数基本相同),其组的平均值几乎相等。

  

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可能能够更好地处理数据。

再次感谢!

3 个答案:

答案 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