0

I have a dataframe formatted like this:

df_before <- 
  tibble(
    key = rep(c('rank', 'name', 'metric'), 5), 
    value = c(
      1, 'name1', 4352, 
      2, 'name2', 2181, 
      3, 'name3', 1399, 
      4, 'name4', 1087, 
      5, 'name5', 1010
    ))

# A tibble: 15 x 2
   key    value
   <chr>  <chr>
 1 rank   1    
 2 name   name1
 3 metric 4352 
 4 rank   2    
 5 name   name2
 6 metric 2181 
 7 rank   3    
 8 name   name3
 9 metric 1399 
10 rank   4    
11 name   name4
12 metric 1087 
13 rank   5    
14 name   name5
15 metric 1010 

I need to get it to this format:

df_after <- 
  tibble(
    rank = 1:5, 
    name = c('name1', 'name2', 'name3', 'name4', 'name5'), 
    metric = c(4352, 2181, 1399, 1087, 1010)
    )

# A tibble: 5 x 3
   rank name  metric
  <int> <chr>  <dbl>
1     1 name1   4352
2     2 name2   2181
3     3 name3   1399
4     4 name4   1087
5     5 name5   1010

I know there are pivot functions in tidyr but I cannot figure out the syntax from the documentation. Tidyverse is preferred but any library or base function is fine.

Frank B.
  • 1,813
  • 5
  • 24
  • 44

3 Answers3

1

in base R you could do:

unstack(df_before,value~key)

  metric  name rank
1   4352 name1    1
2   2181 name2    2
3   1399 name3    3
4   1087 name4    4
5   1010 name5    5

To convert the types into integer/double you could do:

type.convert(unstack(df_before,value~key))
Onyambu
  • 67,392
  • 3
  • 24
  • 53
0

We can create a sequence column and then do the pivot_wider

library(dplyr)
library(tidyr)
library(data.table)
df_before %>% 
   mutate(rn = rowid(key)) %>% 
   pivot_wider(names_from = key, values_from = value) %>%
   select(-rn) %>%
   type.convert(as.is = TRUE)
# A tibble: 5 x 3
#   rank name  metric
#  <int> <chr>  <int>
#1     1 name1   4352
#2     2 name2   2181
#3     3 name3   1399
#4     4 name4   1087
#5     5 name5   1010

or an option with group_split

df_before %>%
    group_split(key = factor(key, levels = unique(key)), .keep = FALSE) %>% 
    bind_cols %>% 
    set_names(unique(df_before$key)

Or using base R

data.frame(split(df_before$value, df_before$key))
#  metric  name rank
#1   4352 name1    1
#2   2181 name2    2
#3   1399 name3    3
#4   1087 name4    4
#5   1010 name5    5
akrun
  • 874,273
  • 37
  • 540
  • 662
0

In data.table we can use dcast :

library(data.table)
dcast(setDT(df_before), rowid(key)~key, value.var = 'value')[, key:= NULL][]

#   metric  name rank
#1:   4352 name1    1
#2:   2181 name2    2
#3:   1399 name3    3
#4:   1087 name4    4
#5:   1010 name5    5
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213