how to use mutate_at and fct_rev() together?

dplyr
mutate
#1

Hi, I have a data set including scale items. I want to reverse all items' scores by using
mutate_at() and fct_rev() together. I illustrated what I want to do below. But R gives an error. How can I reverse all items (x,y and z in this example) at once while using mutate_at() function?

x <- rep(1:3, each=10)
y <- rep(c(2,1,3), each=10)
z <- rep(3:1, each=10)
q <- letters[1:30]

xyzq <- tibble(x,y,z,q)

xyz %>% mutate_at(vars(1:3), funs(fct_rev())) # gives an error
xyz %>% mutate_at(vars(1:3), funs(fct_rev(.))) # gives an error

0 Likes

#2

One reason for getting error is xyz is undefined. You meant to use xyzq, I think.

From your description, it's not clear to me what is your expected output.

Can you please provide a REPRoducible EXample of your problem, mentioning a expected output for a small input?

I failed to find any factor in your example. If you just want to reverse a vector, you may use the rev function.

1 Like

#4

Hi again, thank you for your reply,

Yes I meant xyzq, and yes, x, y and z are not factors. So I understand that I can not use
fct_rev() as x, y and z are not factors.

Here is the revised example.

x <- rep(1:3, each=10)
y <- rep(c(2,1,3), each=10)
z <- rep(3:1, each=10)
q <- letters[1:30]

xyzq <- tibble(x,y,z,q)

This is the original output:

A tibble: 30 x 4

   x     y     z q    


1 1 2 3 a
2 1 2 3 b
3 1 2 3 c
4 1 2 3 d
5 1 2 3 e
6 1 2 3 f
7 1 2 3 g
8 1 2 3 h
9 1 2 3 i
10 1 2 3 j
11 2 1 2 k
12 2 1 2 l
13 2 1 2 m
14 2 1 2 n
15 2 1 2 o

... with 15 more rows

What I want to do is reverse the elements (1,2,3) of x,y and z such that all the values of 1s will become 3, all 2s will stay the same, and all 3s will become 1. In another words, I want to reverse the numbers.

This is the output that I want to see:

A tibble: 30 x 4

x_reversed y_reversed z_reversed q

1 3 2 1 a
2 3 2 1 b
3 3 2 1 c
4 3 2 1 d
5 3 2 1 e
6 3 2 1 f
7 3 2 1 g
8 3 2 1 h
9 3 2 1 i
10 3 2 1 j
11 2 3 2 k
12 2 3 2 l
13 2 3 2 m
14 2 3 2 n
15 2 3 2 o

And this is how I created the reversed tibble:

x_reversed <- rep(3:1, each=10)
y_reversed <- rep(c(2,3,1), each=10)
z_reversed <- rep(1:3, each=10)
q <- letters[1:30]
xyzq_rev <- tibble(x_reversed,y_reversed,z_reversed,q)

I want to make this conversion by using mutate_at() function, as I have too many variables that needs to be reversed.

Thank you again.

0 Likes

#5

I understand what you mean. I think the following does what you want:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

x <- rep(x = 1:3,
         each = 10)
y <- rep(x = c(2, 1, 3),
         each = 10)
z <- rep(x = 3:1,
         each = 10)
q <- letters[1:30]

xyzq <- tibble(x,y,z,q)

xyzq %>%
  mutate_at(.vars = vars(-q),
            .funs = rev)
#> # A tibble: 30 x 4
#>        x     y     z q    
#>    <int> <dbl> <int> <chr>
#>  1     3     3     1 a    
#>  2     3     3     1 b    
#>  3     3     3     1 c    
#>  4     3     3     1 d    
#>  5     3     3     1 e    
#>  6     3     3     1 f    
#>  7     3     3     1 g    
#>  8     3     3     1 h    
#>  9     3     3     1 i    
#> 10     3     3     1 j    
#> # … with 20 more rows

Created on 2019-04-05 by the reprex package (v0.2.1)

1 Like

#7

Accidentally deleted my earlier post, but Yarnabrina's solution is in any case more general. So this is just an addition.

``` r
library(tidyverse, suppressWarnings())


x <- rep(1:3, each=10)
y <- rep(c(2,1,3), each=10)
z <- rep(3:1, each=10)
q <- letters[1:30]


xyzq <- tibble(x,y,z,q)

new <- xyzq %>% 
  mutate_at(vars(x,y,z), function(i) 4 - i)  
glimpse(new)
#> Observations: 30
#> Variables: 4
#> $ x <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
#> $ y <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, ...
#> $ z <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
#> $ q <chr> "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", ...

new1 <- xyzq %>% 
    mutate_at(vars(x,y,z), .funs=list(vers2 = ~rev(.)))

glimpse(new1)
#> Observations: 30
#> Variables: 7
#> $ x       <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, ...
#> $ y       <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, ...
#> $ z       <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, ...
#> $ q       <chr> "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",...
#> $ x_vers2 <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, ...
#> $ y_vers2 <dbl> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, ...
#> $ z_vers2 <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, ...

Created on 2019-04-05 by the reprex package (v0.2.1)

0 Likes

#8

Yes this is what I want, thank you for your help.

0 Likes

closed #9

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.

0 Likes