why mutate does not work here...

I have a code where I originally intended to use mutate, but then found this solution searching the web, which is a bit cryptic to me.

library(tidyverse)

mtcars1 <- mtcars %>% select(contains("d")) %>% {.*(-1)} 

It works, as opposed to this one, which must be somehow erroneous:

mtcars1 <- mtcars %>% select(contains("d")) %>% mutate(. = .*(-1)) 

I do not know why - can you help?

Hello,

The second is not working as it states:

Error in mutate_impl(.data, dots) : 
  Column `.` must be length 32 (the number of rows) or one, not 2

It is working on a columns level here i.e. disp and draft where mutate is expecting something of an exact length of the original dataframe in terms of number of rows (i.e. 32) instead of the 2 it is receiving. I hope this helps?

Please elaborate on what you mean by coding it properly? What output are you expecting?

I expect mutate to do what the code above does - it is multiplying by -1 values in columns with "d" in their names

Then it is adequate and correct to make use of as you have it:

mtcars1 <- mtcars %>% select(contains("d")) %>% {.*(-1)} 

The full stop is essentially telling it to take what is being piped on and then multiply all values that can be multiplied by -1.

@leoncio you can use the below syntax for this. Different variants of mutate, e.g. mutate_at, mutate_if, mutate_all, mutate_each all are intended to accomplish this task. Alternatively, if you have an updated version of dplyr, I believe the function across can also work here.

library(tidyverse)

mtcars %>% 
  select(contains("d")) %>%  # not neccessary unless you only want to see these columns
  mutate_at(vars(contains("d")),list(~.*(-1)))
#>      disp  drat
#> 1  -160.0 -3.90
#> 2  -160.0 -3.90
#> 3  -108.0 -3.85
#> 4  -258.0 -3.08
#> 5  -360.0 -3.15
#> 6  -225.0 -2.76
#> 7  -360.0 -3.21
#> 8  -146.7 -3.69
#> 9  -140.8 -3.92
#> 10 -167.6 -3.92
#> 11 -167.6 -3.92
#> 12 -275.8 -3.07
#> 13 -275.8 -3.07
#> 14 -275.8 -3.07
#> 15 -472.0 -2.93
#> 16 -460.0 -3.00
#> 17 -440.0 -3.23
#> 18  -78.7 -4.08
#> 19  -75.7 -4.93
#> 20  -71.1 -4.22
#> 21 -120.1 -3.70
#> 22 -318.0 -2.76
#> 23 -304.0 -3.15
#> 24 -350.0 -3.73
#> 25 -400.0 -3.08
#> 26  -79.0 -4.08
#> 27 -120.3 -4.43
#> 28  -95.1 -3.77
#> 29 -351.0 -4.22
#> 30 -145.0 -3.62
#> 31 -301.0 -3.54
#> 32 -121.0 -4.11

Created on 2020-12-14 by the reprex package (v0.3.0)

Yes, I just wondered why mutate command does not work when the above does.
the {} instead of mutate are new to me. Thought the mutate command has some minor mistake and after correction would work the same..

Not a bug, you are merely using the wrong syntax, you have to use the across() function inside mutate() if you want to work "across" variables (Or use the old syntax described in the previous comment).

library(dplyr)

mtcars %>% 
    mutate(across(contains("d"), ~.*(-1)))

Ok then, this is much bigger a change than what I thought is needed in the original formula ;). Thanks for that.

Thanks, already got that solution in another post too - it seems I could contain two problems in one post and it would be quicker to solve ;).

Generally speaking, you should ask a single question per topic here to keep things tidy, but related follow up questions are OK too.

Could you refer me to some explanation as to using ~ and . instead of repeating arguments/ writing function(x)..
I somehow do not see this in entry courses in R and their usage eludes me..
e.g. in the example above, what ~ and . stand for, and could they be exchanged into some more "traditional" arguments/functions and work the same?

~ This is for defining lambda functions also called anonymous functions (this is a concept applicable to many programming languages).
. In this context, the "dot" represents each one of the columns you have selected with the contains("d") selection helper.

Yes, you can define named functions.

library(dplyr)

named_function <- function(x) {x * -1}

mtcars %>% 
    mutate(across(contains("d"), named_function))

Many thanks for this clarification, it's helpful.

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.

Thanks, I get it (I did not get such message..) , but then how would one code it properly?