Q:

Preserve NA in output of ifelse statement using paste

I have data that is organized like below M1 - M4, and I use the code from here to generate 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

It looks for a specified number of occurneces of number in the four columns and reports those numbers in M_NEW. Now, I would like to include the numbers 0 and 21 to each of the observations, unless that observation is NA. However, so far, I am unable to paste 0 and 21 to the observations, without also pasting them the NA values. The desired output is include in df below as M_NEW1. How can this be accomplished? It appears that I am missing something with paste here.
# 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))

A:

You can add another if else statement - rather inelegant but gets you there.
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"

