2013-07-05 164 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