我的data.frame
看起来像这样:
dfTall <- frame_data(
~id, ~x, ~y, ~z,
1, "a", 4, 5,
1, "b", 6, 5,
2, "a", 5, 4,
2, "b", 1, 9)
我想把它变成这个:
dfWide <- frame_data(
~id, ~y_a, ~y_b, ~z_a, ~z_b,
1, 4, 6, 5, 5,
2, 5, 1, 4, 9)
目前,我正在这样做
dfTall %>%
split(., .$x) %>%
mapply(function(df,name)
{df$x <- NULL; names(df) <- paste(names(df), name, sep='_'); df},
SIMPLIFY=FALSE, ., names(.)) %>%
bind_cols() %>%
select(-id_b) %>%
rename(id = id_a)
实际上,我需要扩展更多的数字列(即,不只是y
和z
)。我当前的解决方案有效,但它存在问题,例如id
变量的多个副本被添加到最终data.frame
并需要删除。
可以使用tidyr
中的函数(例如spread
?
答案 0 :(得分:4)
可以使用spread
完成,但不能在一个步骤中完成,因为它涉及多个列作为值;您可以首先gather
值列,unite
手动标题,然后spread
:
library(dplyr)
library(tidyr)
dfTall %>%
gather(col, val, -id, -x) %>%
unite(key, col, x) %>%
spread(key, val)
# A tibble: 2 x 5
# id y_a y_b z_a z_b
#* <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1 4 6 5 5
#2 2 5 1 4 9
如果您使用data.table
,则dcast
支持投放多个值列:
library(data.table)
dcast(setDT(dfTall), id ~ x, value.var = c('y', 'z'))
# id y_a y_b z_a z_b
#1: 1 4 6 5 5
#2: 2 5 1 4 9