R 基于不同优先级条件的嵌套ifelse替代方案

R 基于不同优先级条件的嵌套ifelse替代方案,r,R,我想根据其他几个向量的条件创建一个向量。这些条件按优先级的降序排列。这里是一个简单的例子,我正在创建变量“see1”,它应该包含不同的字母,但不包含NA。创建它的优先级是分层的:l1>l2>l3>l4。例如,如果所有其他条件均为NA,则只能将“see1”的状态指定为“l4”;如果“l1”不为NA,则将自动将“l1”的状态指定为“l1”。l1将否决其他列。我使用了嵌套的ifelse来创建“see1” test <- data.frame(id=c("a","b","c","d","e","f

我想根据其他几个向量的条件创建一个向量。这些条件按优先级的降序排列。这里是一个简单的例子,我正在创建变量“see1”,它应该包含不同的字母,但不包含NA。创建它的优先级是分层的:l1>l2>l3>l4。例如,如果所有其他条件均为NA,则只能将“see1”的状态指定为“l4”;如果“l1”不为NA,则将自动将“l1”的状态指定为“l1”。l1将否决其他列。我使用了嵌套的ifelse来创建“see1”

test <- data.frame(id=c("a","b","c","d","e","f"),
               l1=c(NA,NA,"A",NA,"B", NA),
               l2=c(NA,NA,"N","N",NA,NA),
               l3=c("V",NA,NA,NA,"V","V"), 
               l4=c("H","H",NA,NA,rep("H",2)), stringsAsFactors=F)
test$see1 <- ifelse(test$l1%in%c("A", "B"), test$l1,
               ifelse(test$l2%in%"N", "N", 
                  ifelse(test$l3%in%"V", "V",
                        ifelse(test$l4%in%"H","H", NA))))
test

id   l1   l2   l3   l4 see1
1  a <NA> <NA>    V    H    V
2  b <NA> <NA> <NA>    H    H
3  c    A    N <NA> <NA>    A
4  d <NA>    N <NA> <NA>    N
5  e    B <NA>    V    H    B
6  f <NA> <NA>    V    H    V
但是,由于有许多条件/列,此任务变得很麻烦。我已扫描了有关“嵌套ifelse”的类似问题,但没有遇到此问题。

您可以尝试在l\\d”列上使用带有ties.method='first'的max.col创建列索引。cbindwith1:nrowtest`根据行/列索引从“测试”数据集的子集提取元素

nm <- grep('^l\\d+', names(test))
test[nm][cbind(1:nrow(test), max.col(!is.na(test[nm]), 'first'))]
#[1] "V" "H" "A" "N" "B" "V"
您可以在l\\d'列上尝试max.col with ties.method='first'来创建列索引。cbindwith1:nrowtest`根据行/列索引从'test'数据集的子集提取元素

nm <- grep('^l\\d+', names(test))
test[nm][cbind(1:nrow(test), max.col(!is.na(test[nm]), 'first'))]
#[1] "V" "H" "A" "N" "B" "V"

以下是凝聚解决方案:

首先,在我的示例中,对测试中的列重新排序并不是必需的,因为列已排序,但在其他情况下可能很重要

require(dplyr)
require(magrittr) # for piping
test %<>% select(l1,l2, l3, l4)
现在使用合并函数

coalesce2 <- function(...){
 Reduce(function(x,y) {
    i<-which(is.na(x))
    x[i]<-y[i]
    x},
    list(...))
}

test$see1 <- coalesce2(test$l1,test$l2, test$l3, test$l4)
test
或者在magrittr软件包的帮助下

require(magrittr)
test$see1 <- test%$% coalesce2(l1,l2, l3, l4)
test

>    l1   l2   l3   l4 see1
>1 <NA> <NA>    V    H    V
>2 <NA> <NA> <NA>    H    H
>3    A    N <NA> <NA>    A
>4 <NA>    N <NA> <NA>    N
>5    B <NA>    V    H    B
>6 <NA> <NA>    V    H    V

以下是凝聚解决方案:

首先,在我的示例中,对测试中的列重新排序并不是必需的,因为列已排序,但在其他情况下可能很重要

require(dplyr)
require(magrittr) # for piping
test %<>% select(l1,l2, l3, l4)
现在使用合并函数

coalesce2 <- function(...){
 Reduce(function(x,y) {
    i<-which(is.na(x))
    x[i]<-y[i]
    x},
    list(...))
}

test$see1 <- coalesce2(test$l1,test$l2, test$l3, test$l4)
test
或者在magrittr软件包的帮助下

require(magrittr)
test$see1 <- test%$% coalesce2(l1,l2, l3, l4)
test

>    l1   l2   l3   l4 see1
>1 <NA> <NA>    V    H    V
>2 <NA> <NA> <NA>    H    H
>3    A    N <NA> <NA>    A
>4 <NA>    N <NA> <NA>    N
>5    B <NA>    V    H    B
>6 <NA> <NA>    V    H    V

特别是在这个示例中,使用第一个非NA值替换NA,您要查找的操作称为SQL中的coalesce。谢谢你,格雷戈!那有帮助!我已经发布了下面的解决方案。特别是在这个示例中,使用第一个非NA值替换NA,您正在寻找的操作称为SQL中的coalesce。谢谢你,格雷戈!那有帮助!我已经在下面发布了解决方案。