2011-12-14 105 views
4

我有四个逻辑向量数据帧,V1V2V3V4是TRUE或FALSE。我需要基于布尔向量的组合(例如,“无”“V1只有”“V1和V3”“全部”等数据帧的每一行进行分类)。我想这样做,而不采取数据框的子集或嵌套ifelse语句。 任何建议最好的方法来做到这一点?谢谢!比较布尔向量

回答

3

看起来我已经到达在这次晚会上已经很晚了。尽管如此,我仍然可以分享我带来的东西!

这通过处理FALSE/TRUE可能性等位,并在其上操作分配给的v1v2每个组合,和v3 1和8(很像chmod可以表示上*NIX系统权限位)之间的唯一整数。该整数然后用作索引来选择文本描述符向量的适当元素。

(对于演示,我用短短三列,但这种方法很好地扩展了。)

# CONSTRUCT VECTOR OF DESCRIPTIONS 
description <- c("None", "v1", "v2", "v1 and v2", 
       "v3", "v1 and v3", "v2 and v3", "All") 

# DEFINE DESCRIPTION FUNCTION 
getDescription <- function(X) { 
    index <- 1 + sum(X*c(1,2,4)) 
    description[index] 
} 

# TRY IT OUT ON ALL COMBOS OF v1, v2, and v3 
df <- expand.grid(v1=c(FALSE, TRUE), 
        v2=c(FALSE, TRUE), 
        v3=c(FALSE, TRUE)) 
df$description <- apply(df, 1, getDescription) 

# YEP, IT WORKS. 
df 
#  v1 v2 v3 description 
# 1 FALSE FALSE FALSE  None 
# 2 TRUE FALSE FALSE   v1 
# 3 FALSE TRUE FALSE   v2 
# 4 TRUE TRUE FALSE v1 and v2 
# 5 FALSE FALSE TRUE   v3 
# 6 TRUE FALSE TRUE v1 and v3 
# 7 FALSE TRUE TRUE v2 and v3 
# 8 TRUE TRUE TRUE   All 
3

这里有一个方法依靠TRUE/FALSE可以表示为0和1的事实。您可以将布尔值乘以列索引,然后将所有值粘贴在一起。这会告诉你哪一列的每行的值为1。这里有一个例子:

set.seed(1) 
dat <- data.frame(v1 = sample(c(T,F), 10, TRUE), 
        v2 = sample(c(T,F), 10, TRUE), 
        v3 = sample(c(T,F), 10, TRUE), 
        v4 = sample(c(T,F), 10, TRUE) 
       ) 
#End fake data 
#Multiple T/F times the column index 
dat <- dat * rep(seq_len(ncol(dat)), each = nrow(dat)) 
#Paste together in a new column 
dat$v5 <- apply(dat, 1, function(x) paste(x, collapse = "")) 

> dat 
    v1 v2 v3 v4 v5 
1 0 0 3 4 0034 
2 0 2 0 4 0204 
... 

结合下面的有益的意见和附加问题

我会用expand.grid()创建一个查找表,然后写,但是你认为合适的文本标签来表示它们。下面是两列的一个示例:

set.seed(1) 
dat <- data.frame(v1 = sample(c(T,F), 10, TRUE), 
        v2 = sample(c(T,F), 10, TRUE) 
     ) 

#Thanks @Joshua 
dat$comp <- as.character(apply(1 * dat, 1, paste, collapse="")) 

#Look up table 
lookup <- data.frame(comp = apply(expand.grid(0:1, 0:1), 1, paste, collapse = ""), 
        text = c("none", "v1 only", "v2 only", "all"), 
        stringsAsFactors = FALSE 
) 

#Use merge to join the look up table to your data. Note the consistent naming of the comp column 
> merge(dat, lookup) 
    comp v1 v2 text 
1 00 FALSE FALSE none 
2 00 FALSE FALSE none 
3 01 FALSE TRUE v2 only 
.... 
+0

+1做得很好。使用0/1表示的另一种选择是将每个乘以10的幂并加上;这可以通过矩阵乘法完成,就像这个`as.matrix(dat)%*%10^rev(seq_len(ncol(dat)) - 1)`一样。 (或者如果你更喜欢用二进制来思考,则使用2的幂。) – Aaron 2011-12-14 02:55:34

+1

+1,但是我没有看到“列索引”的需要,因为它是由字符串中的“1”的位置定义的。替代方法是`apply(1 * dat,1,paste,collapse =“”)或`do.call(paste,c(1 * dat,sep =“”))``。 – 2011-12-14 03:15:03

+0

谢谢。所以根据你的回答,我想到了以下几点:`v1 < - ifelse(v1 == TRUE,1000,0)``v2 < - ifelse(v1 == TRUE,100,0)``v3 < - ifelse(v1 == TRUE,10,0)``v4 < - ifelse(v1 == TRUE,1,0)``dat $ v5 < - sum(v1,v2,v3,v4)`然后我应该创建一个要查找标签的值列表(例如1111 ==“All”)还是有更好的方法? – 2011-12-14 03:59:51

1
set.seed(123) 
> dat <- data.frame(v1 = sample(c(T,F), 10, TRUE), 
+     v2 = sample(c(T,F), 10, TRUE), 
+     v3 = sample(c(T,F), 10, TRUE), 
+     v4 = sample(c(T,F), 10, TRUE) 
+     ) 
> dat 

第一策略使用的模式来索引的各种组合成字符的以1:1的缺省索引“其他”的载体:

> dat$bcateg <- c("Other", "v2 only", "v1 and v3", "All")[1+ 
+ with(dat, 1*(v2 & !v1 &!v3 &!v4)) 
+ +with(dat, 2*(v1&v3))+ 
+ with(dat, v1&v2&v3&v4)] 
> dat 
     v1 v2 v3 v4 bcateg 
1 TRUE FALSE FALSE FALSE  Other 
2 FALSE TRUE FALSE FALSE v2 only 
3 TRUE FALSE FALSE FALSE  Other 
4 FALSE FALSE FALSE FALSE  Other 
5 FALSE TRUE FALSE TRUE  Other 
6 TRUE FALSE FALSE TRUE  Other 
7 FALSE TRUE FALSE FALSE v2 only 
8 FALSE TRUE FALSE TRUE  Other 
9 FALSE TRUE TRUE TRUE  Other 
10 TRUE FALSE TRUE TRUE v1 and v3 

第二种策略使用“,”的分隔符将TRUE的列名联合起来:

> dat$bcateg2 <-paste(c("","v1")[dat[["v1"]]+1 ], c("","v2")[dat[["v2"]]+1 ], c("","v3")[dat[["v3"]]+1 ], c("","v4")[dat[["v4"]]+1 ], sep = ",") 
> dat 
     v1 v2 v3 v4 bcateg bcateg2 
1 TRUE FALSE FALSE FALSE  Other  v1,,, 
2 FALSE TRUE FALSE FALSE v2 only  ,v2,, 
3 TRUE FALSE FALSE FALSE  Other  v1,,, 
4 FALSE FALSE FALSE FALSE  Other  ,,, 
5 FALSE TRUE FALSE TRUE  Other ,v2,,v4 
6 TRUE FALSE FALSE TRUE  Other v1,,,v4 
7 FALSE TRUE FALSE FALSE v2 only  ,v2,, 
8 FALSE TRUE FALSE TRUE  Other ,v2,,v4 
9 FALSE TRUE TRUE TRUE  Other ,v2,v3,v4 
10 TRUE FALSE TRUE TRUE v1 and v3 v1,,v3,v4 
2

让我把我的帽子环以及

plyr::adply(dat, 1, function(x) paste(names(Filter(isTRUE, x)), collapse = " and ")) 

     v1 v2 v3 v4    V1 
1 TRUE TRUE FALSE TRUE v1 and v2 and v4 
2 TRUE TRUE TRUE FALSE v1 and v2 and v3 
3 FALSE FALSE FALSE TRUE    v4 
4 FALSE TRUE TRUE TRUE v2 and v3 and v4 
5 TRUE FALSE TRUE FALSE  v1 and v3 
6 FALSE TRUE TRUE FALSE  v2 and v3 
7 FALSE FALSE TRUE FALSE    v3 
8 FALSE FALSE TRUE TRUE  v3 and v4 
9 FALSE TRUE FALSE FALSE    v2 
10 TRUE FALSE TRUE TRUE v1 and v3 and v4