2013-07-05 104 views
2

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

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然而,这仅将数据分成2组。

我的实际数据集包含75-150行的任何地方,我需要将它分成5-10组相同均值和相当大小的组。

我在Google上研究过Stack Exchange在过去的几天里,我只是没有太多的运气。任何指导都会很棒。

在此先感谢!

更多细节:

也许我需要提供一些更多的细节,下面我已经包含了真正的数据集。我们是一家运输公司,这个数据集有Driver ID,Miles,Gallons提供。我一直在做的是将数据读入R,添加和MPG列,像这样:

data <- read.csv('filename') 
data$MPG <- data$Miles/data$Gallons 

然后我尝试以下两个提供答案。阿伦的想法给了我几乎相同的团体规模(每组9名成员,10组),但平均数的变化很大,从6.615 - 7.093,这对我来说是一个变化太大的开始。托马斯的想法变得稍微有些紧张,但团队规模与6-13名成员不同。

我们要做的是改善车队MPG,并且我们将以团队为基础的比赛来完成这个任务,所以我需要随机地将车队随同他们一起从相同的团队MPG开始。

也许这有助于并可以引导我们走向正确的方向?我试图用我的编程语言来做这件事,但它每次都会锁定计算机,所以我认为R可能能够更好地处理数据。

再次感谢!

+0

我认为这与[**分区问题**](http://en.wikipedia.org/wiki/Partition_problem)有关,以防您感兴趣。 – Arun

+0

感谢您的回复,您向我提供了一个可用于我生成的数据集的解决方案。 – dcmoody

回答

3

如果类似的方法真的很重要,那么我将下面的一个模拟放在一起,基本上看一组特定组大小(k)的一组不同的数据组合(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线入功能,并且使其从范围内随机抽签你愿意拥有的团体数量。

虽然可能有其他方法可以做到这一点。

+2

似乎并不正确:我认为OP想要将数据拆分为不相交的子集,而您的代码将可能具有共同元素的组进行比较,就我所见 – baptiste

+0

“背包问题”可能是一个很好的搜索关键字在... –

+0

@baptiste你在这段代码中看到重叠集? – Thomas

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 
+0

这似乎与我的答案大致相同... – Thomas

+0

他已经提到,在回答:) – Metrics

1

我能想到的最简单的方法:对数据进行排序,由组数模所有indicies,就大功告成了。如果数据正常分布,我认为应该工作得很好。各组的优势尽可能大小一致。

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