创建多行的“列联”表

时间:2014-03-12 15:30:33

标签: r

让我们考虑这个数据集,其中第一个字段是帐单编号,第二个字段是产品的名称:

df=data.frame(bill=c(1,1,1,1,2,2,2,2,3,3),product=c("A","B","C","B","A","C","E","D","C","D"))

我想计算包含两种产品的每种组合的账单数量,例如在这种情况下是这样的结果(我不想保持计数为0的组合):

#  prod1 prod2 count
#   A     B     1
#   A     C     2
#   A     D     1
#   A     E     1
#   B     C     1
#   C     D     2
#   C     E     1
#   D     E     1

我有一个带循环的解决方案,但它真的不漂亮(而且很慢!):

products=sort(unique(df$product))
bills_list=list()
for (i in 1:length(products)){
   bills_list[[i]]=unique(df[which(df$product==products[i]),"bill"])
}
df2=data.frame(prod1=character(0),prod2=character(0),count=numeric(0))
for (i in 1:(length(products)-1)){
   for (j in (i+1):length(products)){
       Nij=length(intersect(bills_list[[i]],bills_list[[j]]))
       if (Nij>0){
         temp=data.frame(prod1=products[i],prod2=products[j],count=Nij)
         df2=rbind(df2,temp)
       }
   }
}

有没有办法在没有循环的情况下做到这一点?  谢谢你的时间。

4 个答案:

答案 0 :(得分:1)

library(reshape2)

df$product <- as.character(df$product)
products <- t(combn(unique(df$product), 2))
dat <- dcast(bill ~ product, data = df)
##   bill A B C D E
## 1    1 1 2 1 0 0
## 2    2 1 0 1 1 1
## 3    3 0 0 1 1 0


out <- structure(
  data.frame(products, apply(products, 1, function(x) sum(rowSums(dat[x] > 0) == 2) )),
  names = c("prod1", "prod2", "count")
  )

out[out$count != 0,]
##    prod1 prod2 count
## 1      A     B     1
## 2      A     C     2
## 3      A     E     1
## 4      A     D     1
## 5      B     C     1
## 8      C     E     1
## 9      C     D     2
## 10     E     D     1

答案 1 :(得分:1)

以下是plyrdata.table的解决方案。

# needed packages
require(plyr)
require(data.table)
# find the combinations in each of the bills
combs <- ddply(df, .(bill), function(x){
  t(combn(unique(as.character(x$product)),2))
})
colnames(combs) <- c("bill", "prod1", "prod2")
# combine these 
res <- data.table(combs, key=c("prod1", "prod2"))[, .N, by=list(prod1, prod2)]

答案 2 :(得分:1)

这是另一种方法:

library(qdap)

dat <- unlist(lapply(split(df$product, df$bill), function(x) {
    y <- outer(unique(x), unique(x), paste)
    unlist(y[upper.tri(y)])
}))

dat2 <- data.frame(table(dat), stringsAsFactors = FALSE)

colsplit2df(dat2, sep=" ", new.names=paste0("prod", 1:2))

##   prod1 prod2 Freq
## 1     A     B    1
## 2     A     C    2
## 3     A     D    1
## 4     A     E    1
## 5     B     C    1
## 6     C     D    2
## 7     C     E    1
## 8     E     D    1

答案 3 :(得分:0)

res <- table(df$bill, df$product)
##> res
##   
##    A B C D E
##  1 1 2 1 0 0
##  2 1 0 1 1 1
##  3 0 0 1 1 0

res2 <- ifelse(res > 0, 1, 0)
##> res2
##   
##    A B C D E
##  1 1 1 1 0 0
##  2 1 0 1 1 1
##  3 0 0 1 1 0

cor(res2)
##
##     A    B  C    D    E
##A  1.0  0.5 NA -0.5  0.5
##B  0.5  1.0 NA -1.0 -0.5
##C   NA   NA  1   NA   NA
##D -0.5 -1.0 NA  1.0  0.5
##E  0.5 -0.5 NA  0.5  1.0
##Warning message:
##In cor(res2) : the standard deviation is zero

我确实意识到这并没有回答你提出的问题。

但是,它可能会让你更接近答案,大概是你寻求的答案。也就是说,客户订购一种产品对订购其他产品的可能性(正面或负面)的影响是什么。