Emman
Emman

Reputation: 4201

How to partially pivot a dataframe?

I have a table that looks like that:

library(tibble) 

df <-
  tribble(~group, ~median, ~stat_name, ~value,
          "A", 2, "mean", 2,
          "A", 2, "sd",   1,
          "A", 2, "max",  4,
          "B", 2.5, "mean", 1.5,
          "B", 2.5, "sd", 0.7,
          "B", 2.5, "max", 6,
          "C", 1.7, "mean", 2.2,
          "C", 1.7, "sd", 0.5,
          "C", 1.7, "max", 3) 

df
#> # A tibble: 9 x 4
#>   group median stat_name value
#>   <chr>  <dbl> <chr>     <dbl>
#> 1 A        2   mean        2  
#> 2 A        2   sd          1  
#> 3 A        2   max         4  
#> 4 B        2.5 mean        1.5
#> 5 B        2.5 sd          0.7
#> 6 B        2.5 max         6  
#> 7 C        1.7 mean        2.2
#> 8 C        1.7 sd          0.5
#> 9 C        1.7 max         3

Created on 2021-07-27 by the reprex package (v2.0.0)

And I wish to move median -- per group -- to be under stat_name and value, so the desired output is:

## # A tibble: 12 x 3
##    group stat_name value
##    <chr> <chr>     <dbl>
##  1 A     median      2  
##  2 A     mean        2  
##  3 A     sd          1  
##  4 A     max         4  
##  5 B     median      2.5
##  6 B     mean        1.5
##  7 B     sd          0.7
##  8 B     max         6  
##  9 C     median      1.7
## 10 C     mean        2.2
## 11 C     sd          0.5
## 12 C     max         0.3

What would be a straightforward way to do it? (Sorry for the brevity, I don't even know how to name the procedure I'm asking about)

Upvotes: 1

Views: 52

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 389235

You can summarise the dataset and bind it to the original one -

library(dplyr)

df %>%
  group_by(group) %>%
  summarise(value = mean(median), 
            stat_name = 'median') %>%
  bind_rows(df %>% select(-median)) %>%
  arrange(group)

#  group value stat_name
#   <chr> <dbl> <chr>    
# 1 A       2   median   
# 2 A       2   mean     
# 3 A       1   sd       
# 4 A       4   max      
# 5 B       2.5 median   
# 6 B       1.5 mean     
# 7 B       0.7 sd       
# 8 B       6   max      
# 9 C       1.7 median   
#10 C       2.2 mean     
#11 C       0.5 sd       
#12 C       3   max      

Upvotes: 1

Rui Barradas
Rui Barradas

Reputation: 76651

First reshape the stats in stat_name to wide format, then reshape all stats to long format.

library(tidyr)

df %>%
  pivot_wider(
    id_cols = c(group, median),
    names_from = stat_name,
    values_from = value
  ) %>%
  pivot_longer(-group, names_to = "stat_name")

Upvotes: 3

Related Questions