简体   繁体   中英

How can I reshape multiple columns of long data to wide?

structure(tibble(c("top", "jng", "mid", "bot", "sup"), c("369", "Karsa", "knight", "JackeyLove", "yuyanjia"), 
           c("Malphite", "Rek'Sai",  "Zoe", "Aphelios", "Braum"), c("1", "1", "1", "1", "1"), c("7", "5", "7", "5", "0"), 
           c("6079-7578", "6079-7578", "6079-7578", "6079-7578", "6079-7578")), .Names = c("position", "player", "champion", "result", "kills", "gameid"))

Output:

# A tibble: 5 x 6
  position player     champion result kills gameid   
* <chr>    <chr>      <chr>    <chr>  <chr> <chr>    
1 top      369        Malphite 1      7     6079-7578
2 jng      Karsa      Rek'Sai  1      5     6079-7578
3 mid      knight     Zoe      1      7     6079-7578
4 bot      JackeyLove Aphelios 1      5     6079-7578
5 sup      yuyanjia   Braum    1      0     6079-7578

My desired output would be:

structure(list(gameid = "6079-7578", result = "1", player_top = "369", 
    player_jng = "Karsa", player_mid = "knight", player_bot = "JackeyLove", 
    player_sup = "yuyanjia", champion_top = "Malphite", champion_jng = "Rek'Sai", 
    champion_mid = "Zoe", champion_bot = "Aphelios", champion_sup = "Braum", 
    kills_top = "7", kills_jng = "5", kills_mid = "7", kills_bot = "5", 
    kills_sup = "0"), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame")) 

which looks like this:

     gameid result player_top player_jng player_mid player_bot player_sup champion_top champion_jng champion_mid champion_bot champion_sup
1 6079-7578      1        369      Karsa     knight JackeyLove   yuyanjia     Malphite      RekSai          Zoe     Aphelios        Braum
  kills_top kills_jng kills_mid kills_bot kills_sup
1         7         5         7         5         0

I know I should use pivot_wider() and something like drop_na, but I don't know how to do pivot_wider() with mutiple columns and collapse the rows at the same time. Any help would be appreciated.

You can use pivot_wider() for this, defining the "position" variable as the variable that the new column names come from in names_from and the three variables with values you want to use to fill those columns with as values_from .

By default the multiple values_from variables are pasted on to the front of new columns names. This can be changed, but in this case that matches the naming structure you want.

All other variables in the original dataset will be used as the id_cols in the order that they appear.

library(tidyr)
pivot_wider(dat,  
            names_from = "position", 
            values_from = c("player", "champion", "kills"))
#>   result    gameid player_top player_jng player_mid player_bot player_sup
#> 1      1 6079-7578        369      Karsa     knight JackeyLove   yuyanjia
#>   champion_top champion_jng champion_mid champion_bot champion_sup kills_top
#> 1     Malphite      Rek'Sai          Zoe     Aphelios        Braum         7
#>   kills_jng kills_mid kills_bot kills_sup
#> 1         5         7         5         0

You can control the order of your id columns in the output by explicitly writing them out via id_cols . Here's an example, matching your desired output.

pivot_wider(dat, id_cols = c("gameid", "result"), 
            names_from = "position", 
            values_from = c("player", "champion", "kills"))
#>      gameid result player_top player_jng player_mid player_bot player_sup
#> 1 6079-7578      1        369      Karsa     knight JackeyLove   yuyanjia
#>   champion_top champion_jng champion_mid champion_bot champion_sup kills_top
#> 1     Malphite      Rek'Sai          Zoe     Aphelios        Braum         7
#>   kills_jng kills_mid kills_bot kills_sup
#> 1         5         7         5         0

Created on 2021-06-24 by the reprex package (v2.0.0)

Using data.table might help here. In dcast() each row will be identified by a unique combo of gameid and result, the columns will be spread by position, and filled with values from the variables listed in value.var.

library(data.table)
library(dplyr)
df <- structure(tibble(c("top", "jng", "mid", "bot", "sup"), c("369", "Karsa", "knight", "JackeyLove", "yuyanjia"), 
                 c("Malphite", "Rek'Sai",  "Zoe", "Aphelios", "Braum"), c("1", "1", "1", "1", "1"), c("7", "5", "7", "5", "0"), 
                 c("6079-7578", "6079-7578", "6079-7578", "6079-7578", "6079-7578")), .Names = c("position", "player", "champion", "result", "kills", "gameid"))

df2 <- dcast(setDT(df), gameid + result~position, value.var = list('player','champion','kills'))

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