j8sR j8sR - 4 months ago 9
R Question

Why can't I use lapply factor within a function?

I have a data frame with columns labeled q1, q2, q3, etc. I want to create a function that will take arguments (variable name, data frame, level vector, label vector) and change the coded answers to strings.

For example, if q3 is coded 1, 2, or 3, and I want to change that to "bad", "neutral", "good" AND q4 is a series of 4 columns (q4r1, q4r2, q4r3, q4r4) with coded responses 1, 2, or 3 and I want to change those to "red", "blue", "green":

findCol <- function(vn, df) {
if (length(which(grepl(vn, names(df)))) > 1) {
which(grepl(vn, names(df)))
} else {
which(colnames(df)==vn)
}
}


And

labelChng <- function(cv, df, levs, labs) {
if (length(cv) > 1) {
df[cv[1]:cv[length(cv)]] <- lapply(df[cv[1]:cv[length(cv)]], factor,
levels = levs, labels = labs)
} else {
df[cv] <- lapply(df[cv], factor, levels = levs, labels = labs)
}
}


Then

q3c <- findCol("q3", myData)
q3lev <- c(1:3)
q3lab <- c("bad", "neutral", "good")
q4c <- findCol("q4", myData)
q4lev <- c(1:3)
q4lab <- c("red", "blue", "green")


The findCol function works just fine, but when I try to run labelChng, it doesn't actually change anything. When I run this directly in the console:

myData[q4c[1]:q4c[length(q4c)]] <- lapply(myData[q4c[1]:q4c[length(q4c)]], factor,
levels = q4lev, labels = q4lab)


it works just fine, but not when I use:

labelChng(q4c, myData, q4lev, q4lab)


I'm new to this so may be missing something obvious. Any feedback helps.

Answer

Your second function does not return a value and can be simplified:

#Simplified Helpers
findCol <- function(vn, df) grepl(vn, names(df))

labelChng <- function(cv, df, levs, labs) {
  df[cv] <- lapply(df[cv], factor, levels=levs, labels=labs)
  return(df)
}

myData <- data.frame(q1=1:3, q2=3:1, q3=2)
myData
#   q1 q2 q3
# 1  1  3  2
# 2  2  2  2
# 3  3  1  2


q2c <- findCol('q2', myData)
q2lev <- c(1:3)
q2lab <- c("bad", "neutral", "good")
labelChng(q2c, myData, q2lev, q2lab)
#   q1      q2 q3
# 1  1    good  2
# 2  2 neutral  2
# 3  3     bad  2