2012-03-20 42 views
1

我想從整體中選擇滿足某些條件的元素子集。大約有20個元素,每個元素都有多個屬性。我想從一個屬性的固定標準中選擇五個元素提供最少差異的元素,併爲另一個屬性提供最高的平均值。根據標準選擇和標識元素的子集

最後,我想將這個函數應用於多組20個元素。

到目前爲止,我已經能夠「手工」識別子集,但我希望能夠返回值的索引以及返回值本身。

目標:

  1. 我想找到X1屬於至少從一個固定值(55)有差異的該組的五個值的,並提供平均X2的最大值。

  2. 我想這樣做多套。


##### generating example data 
##### this has five groups, each with two variables x1 and x2 
set.seed(271828) 

grp <- gl(5,20) 
x1 <- round(rnorm(100,45, 12), digits=0) 
x2 <- round(rbeta(100,2,4), digits = 2) 
id <- seq(1,100,1) 

##### this is how the data would arrive for me to analyze 
dat <- as.data.frame(cbind(id,grp,x1,x2)) 

的數據將到達在這種格式中,與id作爲各元素的唯一標識符。


##### pulling out the first group for demonstration 
dat.grp.1 <- dat[ which(grp == 1), ] 

crit <- 55 
x <- t(combn(dat.grp.1$x1, 5)) 
y <- t(combn(dat.grp.1$x2, 5)) 

mean.x <- rowMeans(x) 
mean.y <- rowMeans(y) 
k <- (mean.x - crit)^2 

out <- cbind(x, mean.x, k, y, mean.y) 

##### finding the sets with the least amount of discrepancy 
pick <- out[ which(k == min(k)), ] 
pick 

##### finding the sets with low discrepancy and high values of y (means of X2) by "hand" 
sorted <- out[order(k), ] 
head(sorted, n=20) 

隨着pick對於值,我可以看到,X1的值是:

> pick 
        mean.x k       mean.y 
[1,] 55 47 48 48 52  50 25 0.62 0.08 0.31 0.18 0.54 0.346 
[2,] 55 48 48 47 52  50 25 0.62 0.31 0.18 0.48 0.54 0.426 

我想這些元素返回id值,所以我知道我挑選元素:3,8,10,11和18(選擇集合2,因爲與k的差異相同,但是y的平均值很高ER)。

> dat.grp.1 
    id grp x1 x2 
1 1 1 45 0.12 
2 2 1 27 0.34 
3 3 1 55 0.62 
4 4 1 39 0.32 
5 5 1 41 0.18 
6 6 1 29 0.47 
7 7 1 47 0.08 
8 8 1 48 0.31 
9 9 1 35 0.48 
10 10 1 48 0.18 
11 11 1 47 0.48 
12 12 1 31 0.29 
13 13 1 39 0.15 
14 14 1 36 0.54 
15 15 1 36 0.20 
16 16 1 38 0.40 
17 17 1 30 0.31 
18 18 1 52 0.54 
19 19 1 44 0.37 
20 20 1 31 0.20 

這樣做「手工操作」現在可行,但最好將其作爲「解除手腳」。

任何幫助,非常感謝。

+1

您需要定義一個將兩個標準組合成一個數字的函數。然後你可以開始考慮如何找到最佳的。 – Thierry 2012-03-20 16:37:20

回答

2

你幾乎在那裏。您可以將您的sorted定義修改爲

sorted <- out[order(k, -mean.y), ] 

然後sorted[1,](或者,如果你喜歡sorted[1,,drop=FALSE])是你的選擇集。

如果你想要的索引而不是/除了點,那麼你可以提前包括。替換:

x <- t(combn(dat.grp.1$x1, 5)) 
y <- t(combn(dat.grp.1$x2, 5)) 

idx <- t(combn(1:nrow(dat.grp.1), 5)) 
x <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x1"]})) 
y <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x2"]})) 

out包括idx以後。

把INT一起:

##### pulling out the first group for demonstration 
dat.grp.1 <- dat[ which(grp == 1), ] 

crit <- 55 
idx <- t(combn(1:nrow(dat.grp.1), 5)) 
x <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x1"]})) 
y <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x2"]})) 

mean.x <- rowMeans(x) 
mean.y <- rowMeans(y) 
k <- (mean.x - crit)^2 

out <- cbind(idx, x, mean.x, k, y, mean.y) 

##### finding the sets with the least amount of discrepancy and among 
##### those the largest second mean 
pick <- out[order(k, -mean.y)[1],,drop=FALSE] 
pick 

其給出

        mean.x k       mean.y 
[1,] 3 8 10 11 18 55 48 48 47 52  50 25 0.62 0.31 0.18 0.48 0.54 0.426 

編輯:施加超過idx請求的描述;我想要更多的選擇,而不僅僅是我可以在評論中做什麼,所以我將它添加到我的答案中。還將解決循環子集。

idx是一個矩陣(15504 x 5),它的每一行都是數據幀的一組(5)索引。 apply允許通過逐行(逐行爲邊距1)對每行進行操作。有些東西是取值並使用它們來索引dat.grp.1的所需行並提取相應的x1值。我本可以寫dat.grp.1[i,"x1"]作爲dat.grp.1$x1[i]idx的每一行都成爲一列,並且索引到dat.grp.1的結果是行,因此整個事情需要轉置。

如果你喜歡,你可以將循環拆開,看看每一步如何工作。使函數成爲非匿名函數。

f <- function(i) {dat.grp.1[i,"x1"]} 

,並在idx給它的時間通一行。

> f(idx[1,]) 
[1] 45 27 55 39 41 
> f(idx[2,]) 
[1] 45 27 55 39 29 
> f(idx[3,]) 
[1] 45 27 55 39 47 
> f(idx[4,]) 
[1] 45 27 55 39 48 

這些是得到捆綁到x

> head(x,4) 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 45 27 55 39 41 
[2,] 45 27 55 39 29 
[3,] 45 27 55 39 47 
[4,] 45 27 55 39 48 

至於遍歷子集,該plyr庫是這個非常方便。您設置它的方式(將感興趣的子集分配給一個變量並使用它)使變換變得容易。您爲一個子集創建答案所做的每件事都會以該部分作爲參數進入函數。

find.best.set <- function(dat.grp.1) { 
    crit <- 55 
    idx <- t(combn(1:nrow(dat.grp.1), 5)) 
    x <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x1"]})) 
    y <- t(apply(idx, 1, function(i) {dat.grp.1[i,"x2"]})) 

    mean.x <- rowMeans(x) 
    mean.y <- rowMeans(y) 
    k <- (mean.x - crit)^2 

    out <- cbind(idx, x, mean.x, k, y, mean.y) 

    out[order(k, -mean.y)[1],,drop=FALSE] 
} 

這基本上是你以前的東西,但擺脫了一些不必要的任務。

現在將其包裝在plyr調用中。

library("plyr") 
ddply(dat, .(grp), find.best.set) 

這給

grp V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 
1 1 3 8 10 11 18 55 48 48 47 52 50 25 0.62 0.31 0.18 0.48 0.54 0.426 
2 2 8 10 12 15 16 53 35 55 76 56 55 0 0.71 0.20 0.43 0.50 0.70 0.508 
3 3 4 10 15 17 20 47 48 73 55 52 55 0 0.67 0.54 0.28 0.42 0.31 0.444 
4 4 2 11 13 17 19 47 46 70 62 50 55 0 0.35 0.47 0.18 0.13 0.47 0.320 
5 5 3 6 10 17 19 72 40 58 66 39 55 0 0.33 0.42 0.32 0.32 0.51 0.380 

我不知道這是你的結果最好的格式,但它反映你給的例子。

+0

@ BrianDiggs這個很好。你能否在'apply'中描述一下使用'idx'的方法。我有困難纏繞它。任何關於在'grp'級別執行這個操作的想法? – 2012-03-20 17:21:30

+1

@blueandgrey,編輯以解決這些意見。 – 2012-03-20 17:46:36

+0

你,先生,是一個搖滾明星。感謝您的詳細解釋。非常說教。我沒有足夠的代表贊成,但有一天... – 2012-03-20 18:11:25