在r?中转换数据帧为宽格式(转置和连接)

时间:2018-04-12 03:27:08

标签: r dataframe transpose

让我们说

df:
user  actions
 1      A
 1      B
 1      c
 2      A
 2      D
 3      B
 4      C
 4      D

我想转换为这种格式

new_df:
user  action1 action2 action3 
 1      A       B       C
 2      A       D       NA
 3      B       NA      NA
 4      C       D       NA

请注意new_df中的列数等于用户之间的最大操作数。如果用户少于最大动作,则应插入NA。 我该怎么做?

2 个答案:

答案 0 :(得分:2)

您可以使用rle创建一个列来存储action1,action2等。然后使用data.table包中的dcast将数据转换为宽格式。

df$coln <- paste0("actions", unlist(lapply(rle(df$user)$lengths, seq_len)))
data.table::dcast(df, user ~ coln,  value.var="actions")

在回应OP的评论时,你可以用0填写开头,如下所示:

df$coln <- paste0("actions", sprintf("%02d", unlist(lapply(rle(df$user)$lengths, seq_len))))

使用data.table包:

df <- read.table(text="user  actions
1      A
1      B
1      C
1      D
1      E
1      F
1      G
1      H
1      I
1      J
1      K
2      A
2      D
3      B
4      C
4      D", header=TRUE)

library(data.table)
setDT(df)
dcast(setDT(df)[, coln := sprintf("actions%02d", seq_len(.N)), by=.(user)], 
    user ~ coln,  value.var="actions")

答案 1 :(得分:1)

使用tidyverse方法的解决方案

df <- read.table(text = "user  actions
 1      A
 1      B
 1      c
 2      A
 2      D
 3      B
 4      C
 4      D", header = TRUE)

library(tidyr)
library(dplyr)

df %>% 
  group_by(user) %>% 
  mutate(index = paste0("action", row_number())) %>% 
  spread(index, actions) 

#> # A tibble: 4 x 4
#> # Groups:   user [4]
#>    user action1 action2 action3
#>   <int> <fct>   <fct>   <fct>  
#> 1     1 A       B       c      
#> 2     2 A       D       <NA>   
#> 3     3 B       <NA>    <NA>   
#> 4     4 C       D       <NA>

reprex package(v0.2.0)创建于2018-04-11。