recoding multiple Likert variables to numeric values at once without mutate_at

I'm working on data from a survey with 50 questions and I need to make the responses numeric. So far I've been trying to use mutate_at but after about 6 hours of wrestling with it this is the only thing I've produced that won't make an error message:

data %>% 
mutate_at(vars(2:12),
function(x) recode(x,
"None'"=0, 
"A little of the time"=1,
"Sometime"=2,
"Most of the time"=3,
"All the time"=4))  

The results of this are useless for my purposes because all of the "None" responses are displayed as NA and apparently none of the responses are actually being recoded as numbers, just as strings named "1" "2" etc. If I use summary() on any given variable it appears that none of these changes actually stick, since it produces something like

A little of the time 70
All the time 7
etc.

I am able to correctly recode a variable using this code:

data$variable <- as.numeric(recode(
  data$variable,
  "None'"=0, 
  "A little of the time"=1,
  "Sometime"=2,
  "Most of the time"=3,
  "All the time"=4
))  

I have the patience to copy-paste/edit this 50 times but something tells me that's not how you're supposed to do this. I literally started using R yesterday so if I broke a rule or something I'm sorry, I'll delete this post.

EDIT: reproducible example

library("dplyr")
rawdata <- read.csv('filenamet.csv', header = TRUE, sep = ",", na.strings="")
data <- rawdata[-262,-c(1:62,75:83)]

#rename columns
names(data) <- gsub("\\.", "", names(data))
names(data)
data <- dplyr::rename(data,
    frustration = aFrustration,
    sad = bSad,
    guilt = cGuiltyselfblame,
    worry = dWorried,
    irritable = eIrritable,
    fear = fFear,
    angry = gAngry,
    lonely = hLonely,
    helpless = iHelpless,
    hopeless = jHopeless,
    anxious = kAnxious,
    depressed = lDepressed
  )

#recode responses 

data %>% 
mutate_at(vars(2:12),
  ~as.numeric(recode(.,
    "None"=0, 
    "A little of the time"=1,
    "Sometime"=2,
    "Most of the time"=3,
    "All the time"=4)))

#get sum of each row

data$totalscore <- rowSums(data[,c(2:12)],na.rm = TRUE)

Three things for starters:

  1. There's a typo in "None'". Note the extra single quote. It should be "None".
  2. After recoding, run as.numeric to convert the digits from strings to numeric values.
  3. You can use ~ to run the function directly, rather than wrap it inside function().

So the code would be:

data %>% 
mutate_at(vars(2:12), 
          ~as.numeric(recode(.,
                             "None"=0, 
                             "A little of the time"=1,
                             "Sometime"=2,
                             "Most of the time"=3,
                             "All the time"=4))) 

I ran this and got

Error: Evaluation error: object 'x' not found.

See my updated code. I forgot to change the x to .. For future reference, it's helpful if you provide a reproducible example so that we can run your code and test out solutions.

A couple of additional notes: (1) While vars(2:12) works in this case, it's brittle, because it will fail if the order of your columns changes. If there's some regularity to the column names, you can use other column selection methods that will be more robust. (2) mutate_at will continue to work, but the latest version of dplyr has new capabilities that allow you to use mutate whether you're working on one column or multiple columns. see the vignette for details.

I have updated my original question with the example. The code works fine now but when I use str() it shows that all of the variables are still character variables and not numeric.

I'm not sure why that's not working with your data. Your example isn't reproducible as we don't have access to your data, so I'm not able to do any testing. For now, here's a simple example showing that you don't actually need the as.numeric to get numeric columns from recode:

library(tidyverse)

d = tibble(x1=rep(LETTERS[1:3], 2),
           x2=rep(LETTERS[1:3], 2))
d[3, 2] = NA

d
#> # A tibble: 6 x 2
#>   x1    x2   
#>   <chr> <chr>
#> 1 A     A    
#> 2 B     B    
#> 3 C     <NA> 
#> 4 A     A    
#> 5 B     B    
#> 6 C     C

d %>% 
  mutate_at(vars(starts_with("x")), ~recode(., A=1, B=2, C=3)) %>% 
  mutate(total = rowSums(., na.rm=TRUE))
#> # A tibble: 6 x 3
#>      x1    x2 total
#>   <dbl> <dbl> <dbl>
#> 1     1     1     2
#> 2     2     2     4
#> 3     3    NA     3
#> 4     1     1     2
#> 5     2     2     4
#> 6     3     3     6

Created on 2020-07-13 by the reprex package (v0.3.0)

Sorry about wasting your time. I won't do this again.

You didn't waste my time. The purpose of this site is to help people learn how to use R. You're doing pretty well for someone who started learning R two days ago! When you ask questions in the future, all we ask is that you help us help you by providing a reproducible example. Happy coding!

1 Like

4 posts were split to a new topic: record Likert scale values