Consider this data
that needs the summary
measures mean
and sd
on multiple variables,
# Create grouping var; ####
mtcars <- mtcars %>% mutate(
am = case_when(
am == 0 ~ "Automatic",
TRUE ~ "Manual"
)
)
With the following custom function
and purrr
, I can create a baseline table
,
# Summarising function; ####
sum_foo <- function(data, var) {
data %>%
group_by(am) %>%
summarise(
mean = mean( !!sym(var) , na.rm = TRUE),
sd = sd( !!sym(var) , na.rm = TRUE)
) %>%
mutate(across(where(is.double), round, 2)) %>%
group_by(am) %>%
transmute(
value = paste(mean, "(±", sd, ")", sep = ""),
variable = var
) %>%
pivot_wider(
names_from = "am"
)
}
# Execute Function; ####
sum_variables <- c("mpg", "hp", "disp")
sum_variables %>% map(
sum_foo,
data = mtcars
) %>% reduce(
bind_rows
)
Which gives the following output
,
# A tibble: 3 x 3
variable Automatic Manual
<chr> <chr> <chr>
1 mpg 17.15(±3.83) 24.39(±6.17)
2 hp 160.26(±53.91) 126.85(±84.06)
3 disp 290.38(±110.17) 143.53(±87.2)
I want to get the output
without using map
and reduce
, ie. without iterating through the variables with rowwise
or map
.
I'm looking for an alternative tidyverse
-solution!
Maybe you could use this solution:
library(dplyr)
library(tidyr)
library(tibble)
sum_variables %>%
enframe() %>%
rowwise() %>%
mutate(output = list(sum_foo(mtcars, value))) %>%
select(output) %>%
unnest(cols = output)
# A tibble: 3 x 3
variable Automatic Manual
<chr> <chr> <chr>
1 mpg 17.15(±3.83) 24.39(±6.17)
2 hp 160.26(±53.91) 126.85(±84.06)
3 disp 290.38(±110.17) 143.53(±87.2)
Updated Or you could even modify your function in the following way:
sum_foo2 <- function(data, var) {
data %>%
group_by(am) %>%
summarise(across(all_of(var), list(Mean = mean, sd = sd))) %>%
mutate(across(where(is.double), round, 2)) %>%
group_by(am) %>%
summarise(across(ends_with("Mean"), ~ paste(.x, "(±", get(gsub("_Mean", "_sd", cur_column())), ")", sep = ""))) %>%
pivot_longer(!am, names_to = "Mean", values_to = "Val") %>%
pivot_wider(names_from = "am", values_from = "Val")
}
sum_foo2(mtcars, sum_variables)
# A tibble: 3 x 3
Mean Automatic Manual
<chr> <chr> <chr>
1 mpg_Mean 17.15(±3.83) 24.39(±6.17)
2 hp_Mean 160.26(±53.91) 126.85(±84.06)
3 disp_Mean 290.38(±110.17) 143.53(±87.2)
If I am to trim the function above into a more concise version:
sum_foo2 <- function(data, var) {
data %>%
group_by(am) %>%
summarise(across(all_of(var), ~ paste0(round(mean(.x), 2), "(±", round(sd(.x), 2), ")"))) %>%
pivot_longer(!am, names_to = "Mean", values_to = "Val") %>%
pivot_wider(names_from = "am", values_from = "Val")
}
sum_foo2(mtcars, sum_variables)
Without using the function that you wrote, which require an iteration, ie rowwise/map, You could simply do:
sum_variables <- c("mpg", "hp", "disp")
mtcars %>%
group_by(am) %>%
summarise(across(all_of(sum_variables),
~sprintf('%.2f(\u00B1%.2f)', mean(.x), sd(.x))), .groups = 'drop') %>%
data.table::transpose(keep.names = 'variable', make.names = TRUE)
variable Automatic Manual
1 mpg 17.15(±3.83) 24.39(±6.17)
2 hp 160.26(±53.91) 126.85(±84.06)
3 disp 290.38(±110.17) 143.53(±87.20)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With