j8sR
j8sR

Reputation: 3

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.

Upvotes: 0

Views: 66

Answers (2)

Pierre L
Pierre L

Reputation: 28441

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

Upvotes: 3

Dave2e
Dave2e

Reputation: 24079

Another approach is to use the plyr package. The plyr library has two useful revalue and mapvalues functions to covert one set of factors into another. Here is an example:

library(plyr)
df<-data.frame(x=1:3)
df$x<-as.factor(df$x)
q3lev <- c(1:3)
q3lab <- c("bad", "neutral", "good")

df$x<-mapvalues(df$x, from=q3lev, to=q3lab)

Upvotes: 1

Related Questions