2016-10-12 15 views
3

Я ищу, чтобы удалить значение в переменной, если условие другой переменной выполнено. Например:Установка значения в переменной в NA, условие на другую переменную

df$var1[df$condvar == 0] <- NA 

Код выше работает отлично, но мне нужно, чтобы повторить это для десятков большего числа переменных, поэтому var1 выше изменится на var2, var3 и т.д .. Это всегда основано на том же condvar, хотя для половины переменных условие равно df$condvar == 1. Это громоздко повторять эту линию снова и снова, и мне было интересно, был ли более краткий способ кодировать это. Помогла бы одна из функций apply, или мне нужно создать пользовательскую функцию?

В воспроизводимым примере, я ищу, чтобы избежать повторяющийся характер кода ниже:

ex <- mtcars 
ex$mpg[ex$vs == 0] <- NA 
ex$disp[ex$vs == 0] <- NA 
ex$drat[ex$vs == 0] <- NA 
ex$cyl[ex$vs == 1] <- NA 
ex$hp[ex$vs == 1] <- NA 
ex$wt[ex$vs == 1] <- NA 
ex 


        mpg cyl disp hp drat wt qsec vs am gear carb 
Mazda RX4    NA 6 NA 110 NA 2.620 16.46 0 1 4 4 
Mazda RX4 Wag   NA 6 NA 110 NA 2.875 17.02 0 1 4 4 
Datsun 710   22.8 NA 108.0 NA 3.85 NA 18.61 1 1 4 1 
Hornet 4 Drive  21.4 NA 258.0 NA 3.08 NA 19.44 1 0 3 1 
Hornet Sportabout  NA 8 NA 175 NA 3.440 17.02 0 0 3 2 
Valiant    18.1 NA 225.0 NA 2.76 NA 20.22 1 0 3 1 
Duster 360   NA 8 NA 245 NA 3.570 15.84 0 0 3 4 
etc. 

Я был бы совершенно счастлив, если есть одна строка кода, которая применяется ко всем переменным, для которых condvar == 0 и другой для тех переменных, для которых condvar == 1.

+2

' df $ var1 [df $ condvar == 0, c ("var1", "var2", ...)] <- NA' – HubertL

+0

Это не работает. Я не понимаю, как будет работать часть кода ', c (" var1 "," var2 ", ...)'. – Phil

+1

@Phil: HubertL означает 'df [df $ condvar == 0, c (" var1 "," var2 ", ...)] <- NA', который работает отлично. – smci

ответ

5

Вот попытка, которая, как мы надеемся, не слишком сложна. Если вы создали vars вы хотите перебираем, и соответствующий values вы хотите выбрать для индексации, вы можете сделать:

vars <- c("mpg", "disp", "cyl", "hp") 
values <- c(0, 0, 1, 1) 

ex[vars] <- Map(function(x,y) replace(x, ex$vs == y, NA), ex[vars], vals) 

#      mpg cyl disp hp drat wt qsec vs am gear carb 
#Mazda RX4    NA 6 NA 110 3.90 2.620 16.46 0 1 4 4 
#Mazda RX4 Wag   NA 6 NA 110 3.90 2.875 17.02 0 1 4 4 
#Datsun 710   22.8 NA 108.0 NA 3.85 2.320 18.61 1 1 4 1 
#Hornet 4 Drive  21.4 NA 258.0 NA 3.08 3.215 19.44 1 0 3 1 
#Hornet Sportabout  NA 8 NA 175 3.15 3.440 17.02 0 0 3 2 
#Valiant    18.1 NA 225.0 NA 2.76 3.460 20.22 1 0 3 1 
# ... 

Если вы получили только две группы, вы могли бы сделать это проще с помощью несколько заданий, как @HubertL и @Phil, упомянутые в комментариях, но используя Map, вы можете рассматривать многие переменные со многими возможными значениями индекса, причем никогда не распространяются последние 3 строки кода.

+0

Может быть, пример 'mtcars' в моем вопросе поможет понять дальше. Условная переменная фактически не изменяется, просто условие (0 или 1). Это переменная, которую я хочу изменить, которая отличается от строки к строке. – Phil

+0

@Phil - отредактирован, надеюсь, соответствует отредактированному вопросу. – thelatemail

+0

, который тоже неплохо работает, и мне нравится, что он может быть более обобщенным. Я бы никогда не смог это понять. :) – Phil

0

Try:

ifelse(df$var1 == 0, NA, df$var1) 
+1

Это не отвечает на вопрос. – thelatemail

+0

Мне все равно придется повторять ту же линию снова и снова. – Phil

3

dplyr подход с использованием новой экспериментальной case_when функции будет идти что-то вроде:

require(dplyr) 

ex <- mtcars 
ex <- ex %>% 
     mutate(mpg = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$mpg)) %>% 
     mutate(disp = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$disp)) %>% 
     mutate(cyl = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$cyl)) %>% 
     mutate(hp = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$hp)) 

Примечания:

  • Хедли on 2016-06-27 "case_when() is still somewhat experiment and does not currently work inside mutate(). That will be fixed in a future version." Это заняло у меня 40 минут, чтобы получить этот код в этой точке. Вы поняли эту идею. Однажды case_when работает, это будет хорошо.В то же время обходной путь с filter() ниже
  • Вы должны использовать .$var ссылаться на переменную на РИТ
  • Вы должны указать тип НС на РИТ, следовательно, все as.double(NA)
  • TRUE ~ ... определяет положение по умолчанию

Работа с обходной filter():

ex <- rbind(ex %>% filter(vs==0) %>% mutate(mpg=NA, disp=NA), 
      ex %>% filter(vs==1) %>% mutate(cyl=NA, hp=NA)) 

белый ич имеет побочный эффект реорганизуют строки из-за раскол на vs

4

Благодаря @HubertL (который может разместить это как ответ, и я upvote) и @smci:

ex[ex$vs == 0, c("mpg", "disp", ...)] <- NA 
ex[ex$vs == 1, c("cyl", "hp", ...)] <- NA 
+0

'dplyr :: filter()' следует избегать, он будет изменять порядок строк в соответствии с этим разделом по vs – smci

+0

Хорошая точка, я удалю. – Phil