Сохранить NA в выводе оператора ifelse с помощью вставки

У меня есть данные, которые организованы, как показано ниже M1 - M4, и я использую код из здесь для создания M_NEW:

M1    M2      M3      M4      M_NEW
1     1,2     0        1       1
3,4   3,4   1,2,3,4    4       3,4
NA    NA      1        2       NA

Он ищет указанное количество вхождений числа в четырех столбцах и сообщает об этих числах в M_NEW. Теперь я хотел бы включить числа 0 и 21 в каждое из наблюдений, если это наблюдение не NA. Однако пока я не могу вставить 0 и 21 в наблюдения, не вставив в них также значения NA. Желаемый результат включен в df ниже как M_NEW1. Как это можно сделать? Похоже, я что-то упустил с paste здесь.

# sample data
df <- structure(list(M1 = structure(c(3L, 4L, 2L, 2L, 1L, 5L, NA, 6L
), .Label = c("0", "1", "1,2", "1,2,3,4", "1,2,3,4,5", "3,4,5,6,7"
), class = "factor"), M2 = structure(c(3L, NA, 2L, 2L, 1L, 4L, 
NA, 5L), .Label = c("0", "1,2", "1,2,3,4,5", "4,5,6", "4,5,6,7,8,9,10,11,12,13,14"
), class = "factor"), M3 = structure(c(3L, NA, 1L, 1L, 1L, 2L, 
NA, 4L), .Label = c("0", "1,2,3,4", "1,2,3,4,5", "1,2,3,4,5,6,7,8"
), class = "factor"), M4 = structure(c(3L, NA, 1L, 2L, 1L, 5L, 
NA, 4L), .Label = c("0", "1", "1,2,3,4,5,6", "1,2,3,4,5,6,7,8,9,10,11,12", 
"4,5"), class = "factor"), M_NEW1 = structure(c(3L, NA, 1L, 2L, 
1L, 5L, NA, 4L), .Label = c("0,21", "1,0,21", "1,2,3,4,5,0,21", 
"3,4,5,6,7,8,0,21", "4,5,0,21"), class = "factor")), .Names = c("M1", 
"M2", "M3", "M4", "M_NEW1"), class = "data.frame", row.names = c(NA, 
-8L))

# function slightly modified from https://stackoverflow.com/a/23203159/1670053
f <- function(x, n=3) {
  tab <- table(strsplit(paste(x, collapse=","), ","))
  res <- paste(names(tab[which(tab >= n)]), collapse=",")
  return(ifelse(is.na(res), NA, ifelse(res == 0, "0,21", paste(res,",0,21",sep=""))))
  #return(ifelse(is.na(res), ifelse(res == 0, "0,21", NA), paste(res,",0,21",sep=""))) #https://stackoverflow.com/a/17554670/1670053
  #return(ifelse(is.na(res), NA, ifelse(res == 0, "0,21", paste(na.omit(res),",0,21",sep=""))))
  #return(ifelse(is.na(res), as.character(NA), ifelse(res == 0, "0,21", paste(res,",0,21",sep=""))))
}

df$M_NEW2 <- apply(df[, 1:4], 1, f))

person nofunsally    schedule 23.10.2014    source источник


Ответы (1)


Вы можете добавить еще один оператор if else — довольно неэлегантный, но вы там.

f2 <- function(x, n=3) {
  tab <- table(strsplit(paste(x, collapse=","), ","))
  res <- paste(names(tab[which(tab >= n)]), collapse=",")
  res <- ifelse(res %in% c("0", ""), "0,21", res)
  if(res %in% c("NA","0,21")) res else paste(res, "0,21", sep=",") 
  }

apply(df[1:4], 1, f2)

# "1,2,3,4,5,0,21"   "NA"  "0,21"  "1,0,21"  "0,21"  "4,5,0,21"  "NA" 
#   "3,4,5,6,7,8,0,21"
person user20650    schedule 23.10.2014