将与分类变量关联的列扩展为 dplyr/tidyr 的多列,同时保留 id 变量
Expanding columns associated with a categorical variable into multiple columns with dplyr/tidyr while retaining id variable
我有一个 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
)来完成此扩展?
可以用 spread
完成,但不能一步完成,因为它涉及多个列作为值;您可以先 gather
值列,unite
手动 headers 然后 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
我有一个 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
)来完成此扩展?
可以用 spread
完成,但不能一步完成,因为它涉及多个列作为值;您可以先 gather
值列,unite
手动 headers 然后 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