R中数据框的所有组合

时间:2014-10-16 19:23:54

标签: r combinations

我试图从列表中找到所有组合(不是排列,顺序并不重要),每个组合的结构都有各种限制。我知道combn()会做一个简单列表的技巧,我尝试使用sample(),但我的需求更复杂。

我的数据框有三列,名称,类型,成本。我希望找到7个集合中的所有可能的名称组合(所以7个名称),其中一个是类型1,三个是类型2,其余是类型3,总成本小于设置变量。

我完全不知道如何做到这一点,我甚至不确定R是否是正确的语言。我应该尝试使用一些嵌套的if语句进行for循环吗?

> dput(head(sample))
structure(list(Name = structure(c(6L, 8L, 4L, 9L, 2L, 5L), .Label = c("Amber", 
"Cyndi", "E", "Eric", "Hannah", "Jason", "Jesse", "Jim ", "Lisa", 
"Lucy", "Matt", "Ryan", "Tat"), class = "factor"), Type = c(2L, 
3L, 3L, 1L, 3L, 3L), Cost = c(6000L, 6200L, 9000L, 2000L, 8000L, 
4500L)), .Names = c("Name", "Type", "Cost"), row.names = c(NA, 
6L), class = "data.frame")

和我的sessionInfo()

> sessionInfo()
R version 3.1.1 (2014-07-10)
Platform: x86_64-apple-darwin10.8.0 (64-bit)

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] plyr_1.8.1    ggplot2_1.0.0 dplyr_0.2    

loaded via a namespace (and not attached):
 [1] assertthat_0.1   colorspace_1.2-4 digest_0.6.4     grid_3.1.1       gtable_0.1.2     MASS_7.3-33     
 [7] munsell_0.4.2    parallel_3.1.1   proto_0.3-10     Rcpp_0.11.2      reshape2_1.4     scales_0.2.4    
[13] stringr_0.6.2    tools_3.1.1     

示例数据:

Name    Type    Cost
Jason   2   6000
Jim     3   6200
Eric    3   9000
Lisa    1   2000
Cyndi   3   8000
Hannah  3   4500
E       2   7200
Matt    1   3200
Jesse   3   1200
Tat     3   3200
Ryan    1   5600
Amber   2   5222
Lucy    2   1000

如果总费用设置为60k,则可能有一种组合:

Lisa,Jason,Amber,Lucy,Tat,Jesse,Hannah

这是一个可能的组合,因为Lisa是1型,Jason,Amber和Lucy是2型,其余3个是3型,所有7的总成本低于60k。另一种可能的组合是:

Ryan,Jason,Amber,Lucy,Tat,Jesse,Hannah

Ryan已将Lisa替换为第一组合中的1型。成本仍然低于60k。

我试图在上述条件成立的情况下获得所有可能的组合。

1 个答案:

答案 0 :(得分:1)

使用循环的一种可能的解决方案(可能不是最有效的):

# Example data
Name <- c('Jason', 'Jim','Eric', 'Lisa', 'Cyndi', 'Hanna','Jon','Matt',
          'Jerry','Emily','Mary','Cynthia')
Type <- c(2, 1, 3, 3, 2, 3, 3, 1, 2, 2, 3, 2)
Cost <- c(9200, 8200, 9000, 8700, 9100, 8900, 9800, 7800, 9600, 
          9300, 8100, 7800)

df <- data.frame(Name, Type,Cost)
v1 <- subset(df, Type==1)
v2 <- subset(df, Type==2)
v3 <- subset(df, Type==3)

# Get all combinations of desired size of subsets
m1 <- v1$Name
m2 <- combn(v2$Name, 3)
m3 <- combn(v3$Name, 3)

n1 <- length(m1)
n2 <- ncol(m2)
n3 <- ncol(m3)

# put combinations of subsets together
all.combs <- as.list(rep(NA, n1*n2*n3))
idx <- 1
for (i in 1:n1) {
  for (j in 1:n2) {
    for (k in 1:n3) {
      all.combs[[idx]] <- c(as.character(m1[i]),
                            as.character(m2[,j]),
                            as.character(m3[,k]))
      idx <- idx + 1
    }
  }
}

# Check for total cost < 60K
cond <- rep(NA, length(all.combs))
for (i in 1:length(all.combs)) {
   sum <- 0
   for (j in 1:7) {
      sum <- sum + df$Cost[df$Name==all.combs[[i]][j]]
   }
   cond[i] <- sum < 60000
}
res <- all.combs[cond]
res
相关问题