简体   繁体   中英

dplyr: how to use multiple variables in mutate_at funs

I'm trying to generalize this chunk of code:

trimmedMeans %>%
    mutate(Expectation_mean = paste(format(Expectation_mean, digits = 2, nsmall = 2),
                                   "±",
                                   format(Expectation_sd, digits = 2, nsmall = 2)),
           Interesting_mean = paste(format(Interesting_mean, digits = 2, nsmall = 2),
                                   "±",
                                   format(Interesting_sd, digits = 2, nsmall = 2)),
           Useful_mean = paste(format(Useful_mean, digits = 2, nsmall = 2),
                              "±",
                              format(Useful_sd, digits = 2, nsmall = 2)),
           OralPresentation_mean = paste(format(OralPresentation_mean, digits = 2, nsmall = 2),
                                        "±",
                                        format(OralPresentation_sd, digits = 2, nsmall = 2))
    )

I'm trying to do this:

paste.Mean.Sd <- function(m, s){
    paste(format(m, digits = 2, nsmall = 2),
        "±",
        format(s, digits = 2, nsmall = 2)) }

  trimmedMeans2 <- trimmedMeans %>%
    mutate_at(vars(contains('_mean')), funs(paste.Mean.Sd(
      vars(contains('_mean')), vars(contains('_sd'))
    )) )

What I'm getting is something like this:

在此处输入图片说明

What I expected to have is this:

在此处输入图片说明

What am I missing?


EDIT 1

This code gives me the right result for the "left part" (mean) of the string, not for the SD part:

trimmedMeans %>%
    mutate_at(vars(contains('_mean')), funs(paste.Mean.Sd(., str_replace(., "_mean", "_sd"))))

在此处输入图片说明


EDIT 2

The following is the code to reproduce the dataframe I used:

trimmedMeans <- structure(list(TrackName = structure(c(2L, 2L, 2L, 2L, 2L, 2L
), .Label = c("Llytse", "Mneshe", "Phrypa", "Veormi"), class = "factor"), 
    SpeakerName = c("Delta Shelby", "Irvine Fairburn", "Kristine Harland", 
    "Paislee Jež", "Rhianna Clarke", "Spencer Hargrave"), NumOfVoters = c(15L, 
    14L, 5L, 14L, 17L, 19L), Expectation_mean = c(4.6, 5, 4.2, 
    4.07142857142857, 4.41176470588235, 4.73684210526316), Interesting_mean = c(4.46666666666667, 
    5.5, 5, 4.78571428571429, 5.05882352941176, 5.57894736842105
    ), Useful_mean = c(4.6, 5.14285714285714, 4.6, 4.28571428571429, 
    4.52941176470588, 5.42105263157895), OralPresentation_mean = c(4.33333333333333, 
    5.28571428571429, 5.4, 4.85714285714286, 5.17647058823529, 
    5.52631578947368), Expectation_sd = c(0.736788397613007, 
    0.784464540552736, 0.836660026534076, 0.474631146549323, 
    0.870260272089029, 0.561951486949016), Interesting_sd = c(0.639940473422184, 
    0.518874521662771, 0.707106781186548, 0.801783725737273, 
    0.747545001596402, 0.507257273501788), Useful_sd = c(0.9102589898328, 
    1.02710518202619, 0.894427190999916, 0.913873533463375, 1.06757008311068, 
    0.507257273501788), OralPresentation_sd = c(0.975900072948533, 
    0.825420305855557, 0.547722557505166, 0.864437821507567, 
    0.63593377383646, 0.611775290321498)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -6L), vars = c("TrackName", 
"SpeakerName"), drop = TRUE, indices = list(0L, 1L, 2L, 3L, 4L, 
    5L), group_sizes = c(1L, 1L, 1L, 1L, 1L, 1L), biggest_group_size = 1L, labels = structure(list(
    TrackName = structure(c(2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Llytse", 
    "Mneshe", "Phrypa", "Veormi"), class = "factor"), SpeakerName = c("Delta Shelby", 
    "Irvine Fairburn", "Kristine Harland", "Paislee Jež", "Rhianna Clarke", 
    "Spencer Hargrave")), class = "data.frame", row.names = c(NA, 
-6L), vars = c("TrackName", "SpeakerName"), drop = TRUE, .Names = c("TrackName", 
"SpeakerName")), .Names = c("TrackName", "SpeakerName", "NumOfVoters", 
"Expectation_mean", "Interesting_mean", "Useful_mean", "OralPresentation_mean", 
"Expectation_sd", "Interesting_sd", "Useful_sd", "OralPresentation_sd"
))

I found your approach to be challenging, even after reading the Programming with dplyr vignette. Instead, I used tidyr to gather() and spread() the data to get your desired result, which was more intuitive to me.

library(tidyr)

trimmedMeans %>%
  gather(key, value, -TrackName, -SpeakerName, -NumOfVoters) %>%
  mutate_at('value', format, digits = 2, nsmall = 2) %>%
  separate(key, c('var', 'key')) %>%
  group_by(SpeakerName, var) %>%
  spread(key, value) %>%
  group_by(SpeakerName) %>%
  unite(value, mean, sd, sep = " ± ") %>%
  mutate(var = paste0(var, "_sd")) %>%
  spread(var, value)

# A tibble: 6 x 7
# Groups:   SpeakerName [6]
  TrackName SpeakerName NumOfVoters Expectation_sd Interesting_sd
  <fct>     <chr>             <int> <chr>          <chr>         
1 Mneshe    Delta Shel…          15 4.60 ± 0.74    4.47 ± 0.64   
2 Mneshe    Irvine Fai…          14 5.00 ± 0.78    5.50 ± 0.52   
3 Mneshe    Kristine H…           5 4.20 ± 0.84    5.00 ± 0.71   
4 Mneshe    Paislee Jež          14 4.07 ± 0.47    4.79 ± 0.80   
5 Mneshe    Rhianna Cl…          17 4.41 ± 0.87    5.06 ± 0.75   
6 Mneshe    Spencer Ha…          19 4.74 ± 0.56    5.58 ± 0.51   
# ... with 2 more variables: OralPresentation_sd <chr>,
#   Useful_sd <chr>

I solved in the meantime with this trick:

for (characteristic in speaker.characteristcs) {
characteristic_str <- paste0(characteristic, "_str")

trimmedMeans[characteristic_str] <-
  trimmedMeans %>% ungroup() %>% select( contains(characteristic) ) %>%
  tidyr::unite()
}

paste.Mean.Sd <- function(s){
paste(format(as.numeric(strsplit(s, "\\_")[[1]][1]), digits = 2, nsmall = 2),
      "±",
      format(as.numeric(strsplit(s, "\\_")[[1]][2]), digits = 2, nsmall = 2)) }


trimmedMeans %>%
mutate_at(vars(contains('_str')),
          funs(paste.Mean.Sd(.))) %>%
ungroup() %>%
select(SpeakerName, NumOfVoters, contains('_str')) %>%

I don't know if it's possible to get the result with a single statement, using dplyr programming features.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM