分裂矢量使得两组的平均值几乎相等

时间:2012-01-14 22:23:02

标签: r

我有一个包含2个变量A和B的数据框df。我想在第1组和第2组中拆分A,以便mean(df$B[df$group==1])尽可能接近mean(df$B[df$group==2])

或者只是为了表达它,我想要的是在cutp中找到一个能够最小化df$A

的切割点(abs(mean(df$B[df$A<cutp])-mean(df$B[df$A>=cutp]))

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

如果要在变量A上找到阈值,要将数据拆分为两组,以便这两组中B的均值相似,可以为所有可能的切点计算这些均值,并检查何时这些手段之间的距离很小。

# Sample data
n <- 10
d <- data.frame(
  A = rnorm(n),
  B = rnorm(n)
)

# The quantity to minimize
# (You can use a loop instead of apply.)
d$differences <- apply(
  d, 1, 
  # Compute the difference of the means for each value of A
  function (u) { 
    i <- d$A <= u[1]; 
    abs( mean( d$B[which(i)]) - mean(d$B[which(!i)] ) )
  } 
)
# The mean of an empty vector is NaN: discard those values
d$differences[ ! is.finite( d$differences ) ] <- Inf
# Take the minimum
threshold <- d$A[ which.min( d$differences ) ]
# Build the groups
d$group <- ifelse( d$A <= threshold, "group 1", "group 2" )

答案 1 :(得分:1)

我仍然不确定A列如何影响它。您似乎想要创建一个具有两个级别的新列,这两个级别为列B创建〜=平均值。列A显然与创建的新列相关联,但不会直接影响所需的计算。我错过了什么吗?

无论如何,这是一个开始(请注意,这可以更加健壮,但概念验证应该有效)。定义一个你认为可以接受的容差,然后设置一个while循环来创建新的组,直到满足条件,即

FUN <- function(tol){
  df$groups <- sample(1:2, nrow(df), TRUE)

  while(abs(mean(df$B[df$groups == 1]) - mean(df$B[df$groups == 2])) > tol) {
    df$groups <- sample(1:2, nrow(df), TRUE)
  }
  return(df)
}

set.seed(101)
df <- data.frame(A=runif(20),B=runif(20))

#Test it. Means should be less than .02 different and have roughly equivalent sample sizes.
set.seed(101)
out <- FUN(.02)
library(plyr)
> ddply(out, "groups", summarize, n = length(B), mean = mean(B))
  groups  n      mean
1      1 11 0.5229024
2      2  9 0.5037279

我应该注意,如果你设置tol超低,你可以创建一个失控功能,所以如果你的计算机崩溃,不要怪我。