Как я могу создать новую переменную на основе условий в R - PullRequest
3 голосов
/ 14 апреля 2019

Я пытаюсь создать новую переменную, основываясь на некоторых условиях.

Мои данные выглядят как

a   b
1   NA
2   3
3   3
NA  2
NA  NA

То, что я хочу, это переменная c такая, что

  • , когда a не NA, b равно NA, c = a

  • , когда a равно NA,b не NA, c = b

  • , когда a равно NA, b равно NA, c = NA

  • , когда a не NA, b не NA и a == b, c = a

  • , когда aне NA, b это не NA, а a != b, c = "multiple_values"

Как я могу это сделать?

Вроде как ifelse() не могу делать то, что я хочу.

Ответы [ 5 ]

5 голосов
/ 14 апреля 2019

За исключением одного из условий, то есть не-NA элементов в обоих 'a', 'b', и они не равны друг другу, все остальные условия выполняются с coalesce.Таким образом, мы можем сделать case_when, чтобы сгенерировать «множественные значения» на основе последнего условия и всех других, применив coalesce

library(dplyr)
df1 %>%
     mutate(c = case_when(!is.na(a) & !is.na(b) & a != b ~ "multiple_values", 
               TRUE ~ as.character(coalesce(a, b))))
#   a  b               c
#1  1 NA               1
#2  2  3 multiple_values
#3  3  3               3
#4 NA  2               2
#5 NA NA            <NA>

data

df1 <- structure(list(a = c(1L, 2L, 3L, NA, NA), b = c(NA, 3L, 3L, 2L, 
 NA)), class = "data.frame", row.names = c(NA, -5L))
4 голосов
/ 14 апреля 2019

В базе R вы можете использовать within.

dat <- within(dat, {
  c <- NA
  c[!is.na(a) & is.na(b)] <- a[!is.na(a) & is.na(b)]
  c[is.na(a) & !is.na(b)] <- b[is.na(a) & !is.na(b)]
  # # c[is.na(a) & is.na(b)] <- NA  # redundant
  c[!is.na(a) & !is.na(b) & a == b] <- a[!is.na(a) & !is.na(b) & a == b]
  c[!is.na(a) & !is.na(b) & a != b] <- "multiple_values"
})

dat
#    a  b               c
# 1  1 NA               1
# 2  2  3 multiple_values
# 3  3  3               3
# 4 NA  2               2
# 5 NA NA            <NA>

Данные: dat <- data.frame(a=c(1:3, NA, NA), b=c(NA, 3, 3, 2, NA))

2 голосов
/ 14 апреля 2019

Вот еще один базовый R-ответ, который использует mapply для циклического перебора пар значений, простую функцию, которая объединяет их и отбрасывает NA, и использует switch для определения результата.

df1$c <-
 mapply(function(x, y) {
                 z <- c(x, y)
                 z <- unique(z[!is.na(z)])
                 switch(length(z) + 1L, NA, z, "many")
        }, df1$a, df1$b)

, который возвращает

df1
   a  b    c
1  1 NA    1
2  2  3 many
3  3  3    3
4 NA  2    2
5 NA NA <NA>
2 голосов
/ 14 апреля 2019

ifelse может делать то, что вы хотите, но просто будет много вложенных операторов

df$c <- with(df, ifelse(!is.na(a) & is.na(b), a, 
           ifelse(is.na(a) & !is.na(b), b, 
              ifelse(is.na(a) & is.na(b), NA, 
                ifelse(!is.na(a) & !is.na(b) & a == b, a, "multiple_values")))))


df
#   a  b               c
#1  1 NA               1
#2  2  3 multiple_values
#3  3  3               3
#4 NA  2               2
#5 NA NA            <NA>
1 голос
/ 14 апреля 2019

Используя data.table, вы можете:

df1 <- structure(list(a = c(1L, 2L, 3L, NA, NA), b = c(NA, 3L, 3L, 2L, 
                                                       NA)), class = "data.frame", row.names = c(NA, -5L))
library(data.table)
df1 <- as.data.table(df1)
df1[, c:="NONE"]
df1[!is.na(a) & is.na(b), c:=a] 
df1[is.na(a) & !is.na(b), c:=b] 
df1[is.na(a) & is.na(b),  c:=NA] 
df1[!is.na(a) & !is.na(b) & a==b,  c:=a] 
df1[!is.na(a) & !is.na(b) & a!=b,  c:="multiple values"] 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...