如何为R中的多个列的值大于其他值的子集行

时间:2018-03-20 10:32:32

标签: r datatable

我有以下data.table

library(data.table)
dt <- data.table(V1=c(1,3,1,0,NA,0),
                 V2=c(1,0,1,0,1,3),
                 Q1=c(3,5,10,14,0,3),
                 Q2=c(0,1,8,NA,0,NA))

我想添加一个值为1的新列:

如果任何V1V2的值大于2,    如果任何Q1Q2的值大于0

所以最后我想要用这样的东西:

> dt
   V1 V2 Q1 Q2 new
1:  1  1  3  0   0
2:  3  0  5  1   1
3:  1  1 10  8   0
4:  0  0 14 NA   0
5: NA  1  0  0   0
6:  0  3  3 NA   1

修改 原则上我希望有2个列名称向量,所以像v_columms <- names(dt)[names(dt) %like%"V"]q_columms <- names(dt)[names(dt) %like%"q"]这样的东西使用这些

3 个答案:

答案 0 :(得分:1)

我们可以使用melt来处理多个列,方法是在patterns中指定measure以将其转换为'long'格式,然后应用条件

dt[, new := melt(dt, measure = patterns("V", "Q"))[,  
      +(any(value1 > 2) & any(value2 > 0)),rowid(variable)]$V1]
dt
#   V1 V2 Q1 Q2 new
#1:  1  1  3  0   0
#2:  3  0  5  1   1
#3:  1  1 10  8   0
#4:  0  0 14 NA   0
#5: NA  1  0  0   0
#6:  0  3  3 NA   1

或者没有melt,如果只有两组列,则

vs <- grep("V", names(dt))
qs <- grep("Q", names(dt))
dt[, new := +(Reduce(`|`, lapply(.SD[, ..vs], `>`, 2)) &
              Reduce(`|`, lapply(.SD[, ..qs], `>`, 0)))]

答案 1 :(得分:1)

使用dplyr以及case_whenif_else

dt %>%
   mutate(new = case_when((V1 > 2 | V2 > 2) & (Q1 > 0 | Q2) > 0 ~ 1,
                     TRUE ~ 0))

dt %>%
   mutate(new = if_else((V1 > 2 | V2 > 2) & (Q1 > 0 | Q2 > 0), 1 , 0))

  V1 V2 Q1 Q2 new
1  1  1  3  0   0
2  3  0  5  1   1
3  1  1 10  8   0
4  0  0 14 NA   0
5 NA  1  0  0   0
6  0  3  3 NA   1

答案 2 :(得分:1)

这是另一种带有辅助函数的方法:

foo <- function(.dt, cols, vals, na.rm = TRUE) {
  rowSums(.dt[, cols, with=FALSE] > vals, na.rm = na.rm) > 0 
}

bar <- function(.dt, cols_list, vals_list) {
  as.integer(Reduce("&", Map(function(cols, vals) foo(.dt, cols, vals), cols_list, vals_list)))
}

dt[, new := bar(.SD, list(v_columms, q_columms), list(2, 0))]