2016-06-13 76 views
1

我试图获得一个向量,它的值取决于数据帧中的两个(也许更多)列的因子X。所以它可以有两个以上的层次。使用if ... else if ... else语句创建一个向量R

有一种简单的方法来使用C/C++来执行它 - 就像for循环中的条件语句一样。比方说,如果我在一个数据帧MATRIX构建X从值在两个布尔列Col1Col2,我可以很容易地做到这一点是:

X=vector() 
for (i in 1:nrow(MATRIX)) { 
    if (MATRIX$Col1[i]==1 && MATRIX$Col2[i]==1) { 
    X[i] = "both" 
    } else if (MATRIX$Col1[i]==1) { 
    X[i] = "col1" 
    } else if (MATRIX$Col2[i]==1) { 
    X[i] = "col2" 
    } else { 
    X[i] = "none" 
    } 
} 

问题是,obviosly,在大dataframes它需要很多时间跑步。我应该使用矢量化来优化这个,但我看不到方式,因为*应用,ifelse任何似乎不帮助是这样的任务,其中结果不是布尔值。

任何想法?

+0

只是转换'如果... else'到'ifelse()'和下降的循环。 – zx8754

回答

2

这里有几个方法可以做到这一点:

最类似于现有的方法是:

X <- ifelse(MATRIX$Col1==1, 
      ifelse(MATRIX$Col2==1,"both","col1"), 
      ifelse(MATRIX$Col2==1,"col2","none")) 

它可以稍快做:

x <- rep(NA,nrow(MATRIX)) 
x[MATRIX$Col1[i]==1 && MATRIX$Col2[i]==1] <- "both" 
x[MATRIX$Col1[i]==1 && !MATRIX$Col2[i]==1] <- "col1" 
x[!MATRIX$Col1[i]==1 && MATRIX$Col2[i]==1] <- "col2" 
x[!MATRIX$Col1[i]==1 && !MATRIX$Col2[i]==1] <- "none" 

但它的很难看到所有案例是否已被代码覆盖

注:

  • 看起来像MATRIX真的是data.frame;学习要精确到关于你的数据类型可以真正帮助你调试代码。
  • 如果MATRIX$Col1确实是布尔值,则可以删除==1比较, 这会浪费时间,方法是将矩阵转换为数字,然后再对 进行等式测试。
  • 对我来说,最TRANSPARANT的方法是创建 小data.frame预计输出Col1中,col2的和 的可能值,并与现有data.frame合并这一点,但 这可能无法做到高效。
2

我们可以用factor

# dummy data 
set.seed(1) 
MATRIX <- data.frame(Col1 = sample(0:1, 10, replace = TRUE), 
        Col2 = sample(0:1, 10, replace = TRUE)) 

# using factor 
cbind(MATRIX, 
     X = factor(paste(as.numeric(MATRIX$Col1 == 1), 
         as.numeric(MATRIX$Col2 == 1), sep = "_"), 
       levels = c("0_0", "0_1", "1_0", "1_1"), 
       labels = c("none", "col2", "col1", "both"))) 

#  Col1 Col2 X 
# 1  0 0 none 
# 2  0 0 none 
# 3  1 1 both 
# 4  1 0 col1 
# 5  0 1 col2 
# 6  1 0 col1 
# 7  1 1 both 
# 8  1 1 both 
# 9  1 0 col1 
# 10  0 1 col2