2015-03-18 4 views
1

Я хотел бы создать вектор, основанный на условиях нескольких других векторов. Условия находятся в порядке убывания приоритета. Вот простой пример, в котором я создаю переменную 'see1', которая должна содержать разные буквы (но не NA). Приоритет для его создания является иерархическим: l1> l2> l3> l4. Например. «see1» может быть присвоен статус «l4», если все остальные условия равны NA, и ему будет автоматически присвоено состояние «l1», если «l1» не является NA («l1» перекрывает другие столбцы). Я использовал вложенный ifelse для создания 'see1'.Альтернатива вложенным ifelse на основе условий с различным приоритетом

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», но не столкнулся с этой проблемой.

+1

В этом примере, в частности, (замена NA с первым не-NA значение), операция вы ищете называется 'coalesce' в SQL. [Вот хороший вопрос о его реализации в R] (http://stackoverflow.com/q/19253820/903061). – Gregor

+0

Спасибо, Грегор! Это помогло! Я разместил решение ниже. – Tomiris

ответ

2

Вот это COALESCE-решение:

Во-первых, изменить порядок столбцов в тесте (не обязательно в моем примере, как было приказано колонны, но может быть важным в других случаях)

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 
2

Вы можете попробовать max.col с ties.method='first' на l\\d' columns to create the column index. cbind with 1: nrow (тест) `извлечь элементы из подмножества набора данных«»тест на основе индекса строки/столбца.

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" 

Или некоторые варианты использования apply

apply(test[nm], 1, function(x) x[Position(function(y) !is.na(y), x)]) 
#[1] "V" "H" "A" "N" "B" "V" 

    apply(test[nm], 1, function(x) x[!is.na(x)][1]) 
    #[1] "V" "H" "A" "N" "B" "V" 
+0

Спасибо @akrun. Это также работает как шарм. – Tomiris

Смежные вопросы