Home > front end >  Using mutate across with sprintf
Using mutate across with sprintf

Time:05-13

I have a number of columns that I want to show to 2 decimal places using sprintf. I have difficulty getting this to work with mutate(across)

The first block of code shows the result without using the across function and the 2nd block of code shows my attempt so far but the error message is:

Error: Problem with mutate() input ..1. x 'fmt' is not a character vector i Input ..1 is across(c(Sepal.Length, Sepal.Width), ~sprintf(.x, "%0.2f")).

Can anyone suggest an amendment?

library(tidyverse)
iris%>%
mutate(
  Sepal.Length = sprintf("%0.2f", Sepal.Length),
  Sepal.Width = sprintf("%0.2f", Sepal.Width))

iris%>%
  mutate(across(c(Sepal.Length, Sepal.Width), ~ sprintf(.x,  "%0.2f")))

CodePudding user response:

The reason is that the first argument of ?sprintf is fmt. If we pass arguments without name, then the first argument can be assumed as fmt

sprintf(fmt, ...)

library(dplyr)
iris%>%
  mutate(across(c(Sepal.Length, Sepal.Width), ~ sprintf("%0.2f", .x)))

-output

 Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1         5.10        3.50          1.4         0.2  setosa
2         4.90        3.00          1.4         0.2  setosa
3         4.70        3.20          1.3         0.2  setosa
4         4.60        3.10          1.5         0.2  setosa
5         5.00        3.60          1.4         0.2  setosa
6         5.40        3.90          1.7         0.4  setosa
...

Otherwise specify as named argument while changing the default order

iris%>%
  mutate(across(c(Sepal.Length, Sepal.Width),
     ~ sprintf(.x,  fmt = "%0.2f")))

CodePudding user response:

library(tidyverse)
head(iris)
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

iris is only to one decimal place, the following runif runs are a better example to demonstrate on.

set.seed(100)
as_tibble(replicate(4, runif(20, 0, 1))) %>% 
  mutate(across(c(V1, V2), round, 2))
#> Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if `.name_repair` is omitted as of tibble 2.0.0.
#> Using compatibility `.name_repair`.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
#> # A tibble: 20 × 4
#>       V1    V2    V3     V4
#>    <dbl> <dbl> <dbl>  <dbl>
#>  1  0.31  0.54 0.331 0.464 
#>  2  0.26  0.71 0.865 0.647 
#>  3  0.55  0.54 0.778 0.961 
#>  4  0.06  0.75 0.827 0.676 
#>  5  0.47  0.42 0.603 0.445 
#>  6  0.48  0.17 0.491 0.358 
#>  7  0.81  0.77 0.780 0.456 
#>  8  0.37  0.88 0.884 0.445 
#>  9  0.55  0.55 0.208 0.245 
#> 10  0.17  0.28 0.307 0.694 
#> 11  0.62  0.49 0.331 0.412 
#> 12  0.88  0.93 0.199 0.328 
#> 13  0.28  0.35 0.236 0.573 
#> 14  0.4   0.95 0.275 0.967 
#> 15  0.76  0.7  0.591 0.662 
#> 16  0.67  0.89 0.253 0.625 
#> 17  0.2   0.18 0.123 0.857 
#> 18  0.36  0.63 0.230 0.775 
#> 19  0.36  0.99 0.598 0.834 
#> 20  0.69  0.13 0.211 0.0915

Using round is easier and arguably more readable to use in this case.

  •  Tags:  
  • r
  • Related