How to recode Likert scale to many variables

Hi,
I would like to recode a few variables in order for them to have the same Likert scale coding.
I have done it easily in SPSS but somehow I can't replicate it in R.
So I have two questions:

  1. Maybe is there a package to transfer spss files to R with recoded values left intact ?
  2. How to allocate these Likert scale re-coding to many (d1:d9) variables in R at once ?

I feel that I should use mutate_at and across functions, but would be grateful for hint how to start.

myLikertdata <- structure(list(year = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L), .Label = c("pre-clinical", "clinical"), class = "factor"), 
    d1 = c(NA, NA, 1L, 2L, 1L, NA, 4L, 1L, 2L, 2L), d2 = c(NA, 
    NA, 1L, 2L, 1L, NA, 4L, 1L, 2L, 2L), d3 = c(NA, NA, NA, 2L, 
    1L, NA, 3L, NA, 2L, 2L), d4 = c(NA, NA, NA, 2L, NA, NA, 4L, 
    4L, 1L, 1L), d5 = c(3L, 4L, 4L, 2L, 1L, 1L, 1L, 4L, 4L, 3L
    ), d6 = c(2L, 1L, NA, 2L, 2L, NA, 1L, 1L, NA, 3L), d7 = c(4L, 
    2L, NA, 2L, 2L, NA, 3L, 4L, 2L, 4L), d8 = c(2L, 2L, NA, 2L, 
    2L, NA, 3L, 4L, 3L, 4L), d9 = c(1L, NA, NA, 2L, 1L, NA, NA, 
    1L, 1L, 1L)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -10L), groups = structure(list(year = structure(1:2, .Label = c("pre-clinical", 
"clinical"), class = "factor"), .rows = structure(list(1:6, 7:10), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -2L), .drop = TRUE))

myLikertdata$year <- factor(myLikertdata$year, levels=c('1','2'), labels=c('pre-clinical','clinical'))

Likert_scale <- c("not reduced" = 1, "slightly reduced" = 2, " 
moderately reduced" = 3, "strongly reduced" = 4)

and I would like to apply this Likert_scale to all variables from d1 to d9.

Any help would be much appreciated.

To answer your first question, there is. You can get all the preserved values and levels from SPSS in R via Haven: https://haven.tidyverse.org/ (have a look here at Haven specifically).

On your second point you will have to give slightly more clarity on what you mean. Do you mean you want to replace those numeric values with those actual encoded values? Or do you want to change all those variables from d1 to d9 into factors with those levels?

Hi @GreyMerchant and thank you,
I have used "haven" package and I used "sjlabelled" as well in order to compare the import functions.
I want to have like it in SPSS where I have got it arranged as follows:
obraz

This is very good question about what I mean.
I think I do not want it (d1 to d9) as factors as my variable year is a factor with two levels: "pre-clinical" and "clinical", so I guess that I would like to have them as numbers (as numeric) with labels attached to it.
This is possible in SPSS and I hope to get the same analogy in R here.
Correct me please if I am wrong.
Additionally, my dataframe called myLikertdata looks like this:

but I want it for example to look like that:

obraz

but still to be a factor with levels 1 and 2 and labels: 1 = "pre-clinical" and 2 = "clinical".
I apologize for confusion as I learn and try to understand it better. So I am sure that year variable should be a factor but variables d1 to d9 I think they should stay numerical to make some calculations with them but I want to have it recoded with following descriptions (labels):

"not reduced" = 1, "slightly reduced" = 2, " moderately reduced" = 3, "strongly reduced" = 4

And I want to apply this recoding to all of them at once. I hope it makes sense. Zeros were correctly changed onto Nas by "haven" as "not applicable".
kind regards,
Andrzej

I don't know anything about SPSS, so I may be misunderstanding what you want. I don't think R has an exact analog of the "labels" you want to apply to the values of d1:d9. A factor seems to be the closest thing. To change d1:d9 to factors in one step, you can use the mutate and across functions from the dplyr package.

library(dplyr)
myLikertdata <- structure(list(year = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
                                                  2L, 2L, 2L), .Label = c("pre-clinical", "clinical"), class = "factor"), 
                               d1 = c(NA, NA, 1L, 2L, 1L, NA, 4L, 1L, 2L, 2L), 
                               d2 = c(NA,NA, 1L, 2L, 1L, NA, 4L, 1L, 2L, 2L), 
                               d3 = c(NA, NA, NA, 2L, 1L, NA, 3L, NA, 2L, 2L), 
                               d4 = c(NA, NA, NA, 2L, NA, NA, 4L, 4L, 1L, 1L), 
                               d5 = c(3L, 4L, 4L, 2L, 1L, 1L, 1L, 4L, 4L, 3L), 
                               d6 = c(2L, 1L, NA, 2L, 2L, NA, 1L, 1L, NA, 3L), 
                               d7 = c(4L,2L, NA, 2L, 2L, NA, 3L, 4L, 2L, 4L), 
                               d8 = c(2L, 2L, NA, 2L, 2L, NA, 3L, 4L, 3L, 4L), 
                               d9 = c(1L, NA, NA, 2L, 1L, NA, NA, 1L, 1L, 1L)), 
                          class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L), 
                          groups = structure(list(year = structure(1:2, .Label = c("pre-clinical", "clinical"), class = "factor"), 
                                                  .rows = structure(list(1:6, 7:10), ptype = integer(0), class = c("vctrs_list_of","vctrs_vctr", "list"))), 
                                             class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L), .drop = TRUE))


Likert_labels <- c("not reduced", "slightly reduced", "moderately reduced", "strongly reduced")
myLikertdata
#> # A tibble: 10 x 10
#> # Groups:   year [2]
#>    year            d1    d2    d3    d4    d5    d6    d7    d8    d9
#>    <fct>        <int> <int> <int> <int> <int> <int> <int> <int> <int>
#>  1 pre-clinical    NA    NA    NA    NA     3     2     4     2     1
#>  2 pre-clinical    NA    NA    NA    NA     4     1     2     2    NA
#>  3 pre-clinical     1     1    NA    NA     4    NA    NA    NA    NA
#>  4 pre-clinical     2     2     2     2     2     2     2     2     2
#>  5 pre-clinical     1     1     1    NA     1     2     2     2     1
#>  6 pre-clinical    NA    NA    NA    NA     1    NA    NA    NA    NA
#>  7 clinical         4     4     3     4     1     1     3     3    NA
#>  8 clinical         1     1    NA     4     4     1     4     4     1
#>  9 clinical         2     2     2     1     4    NA     2     3     1
#> 10 clinical         2     2     2     1     3     3     4     4     1
myLikertdata <- myLikertdata |> 
  mutate(across(.cols = d1:d9,
                .fns = factor, levels=1:4,labels = Likert_labels))
myLikertdata
#> # A tibble: 10 x 10
#> # Groups:   year [2]
#>    year         d1               d2    d3    d4    d5    d6    d7    d8    d9   
#>    <fct>        <fct>            <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
#>  1 pre-clinical <NA>             <NA>  <NA>  <NA>  mode~ slig~ stro~ slig~ not ~
#>  2 pre-clinical <NA>             <NA>  <NA>  <NA>  stro~ not ~ slig~ slig~ <NA> 
#>  3 pre-clinical not reduced      not ~ <NA>  <NA>  stro~ <NA>  <NA>  <NA>  <NA> 
#>  4 pre-clinical slightly reduced slig~ slig~ slig~ slig~ slig~ slig~ slig~ slig~
#>  5 pre-clinical not reduced      not ~ not ~ <NA>  not ~ slig~ slig~ slig~ not ~
#>  6 pre-clinical <NA>             <NA>  <NA>  <NA>  not ~ <NA>  <NA>  <NA>  <NA> 
#>  7 clinical     strongly reduced stro~ mode~ stro~ not ~ not ~ mode~ mode~ <NA> 
#>  8 clinical     not reduced      not ~ <NA>  stro~ stro~ not ~ stro~ stro~ not ~
#>  9 clinical     slightly reduced slig~ slig~ not ~ stro~ <NA>  slig~ mode~ not ~
#> 10 clinical     slightly reduced slig~ slig~ not ~ mode~ mode~ stro~ stro~ not ~

Created on 2022-01-08 by the reprex package (v2.0.1)
If you want to do calculations with those values, it is easier to leave them as numeric. Maybe you need to use a modified workflow in R compared to what you do in SPSS. If you can describe what you are having trouble with, e.g. making correctly labeled graphs, someone might be able to provide specific guidance.

2 Likes

Thank you very much @FJCC , that was very helpful.
I was just suprised that when I convert a variable to a factor, it displays levels, but when I add labels as well, it displays those labels as levels.

FJCC's solution for mutate across is ideal and will work well.

In terms of getting the most out of Haven, did you follow the steps described here based on the function labelled ? Conversion semantics • haven

As mentioned on this page:

The goal of haven is not to provide a labelled vector that you can use everywhere in your analysis. The goal is to provide an intermediate datastructure that you can convert into a regular R data frame. You can do this by either converting to a factor or stripping the labels:

and then later on:

See the documentation for as_factor() for more options to control exactly what the factor uses for levels.

There are a few packages that help with processing SPSS (or .sav) format pages. You can use haven, foreign or sjlabelled. Alternative, you can recode using dplyr::case_when.

df <- df %>%
mutate(x = case_when(x == 1 ~ "Strongly Disagree",
                     x == 2 ~ "Disagree",
                     x== 3 ~ "Neutral",
                     x ==4 ~ "Disagree",
                     x ==5 ~ "Strongly Disagree",
                     x == 99 ~ "NA"))

The function is a vectorised version of an ifelse statement. You can map it across the relevant columns as well.

Thank you for your kind reply.

There is a trouble with these labels in R, I still struggle with it:

https://community.rstudio.com/t/how-to-remove-a-deeper-attribute-from-a-variable/126495