假设我有一个小组。
library(tidyverse)
tib <- as.tibble(list(record = c(1:10),
gender = as.factor(sample(c("M", "F"), 10, replace = TRUE)),
like_product = as.factor(sample(1:5, 10, replace = TRUE)))
tib
# A tibble: 10 x 3
record gender like_product
<int> <fctr> <fctr>
1 1 F 2
2 2 M 1
3 3 M 2
4 4 F 3
5 5 F 4
6 6 M 2
7 7 F 4
8 8 M 4
9 9 F 4
10 10 M 5
我想用1和0编码我的数据代码,以便数据看起来更像/更少。
# A tibble: 10 x 8
record gender_M gender_F like_product_1 like_product_2 like_product_3 like_product_4 like_product_5
<int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 0 1 0 0 1 0 0
2 2 0 1 0 0 0 0 0
3 3 0 1 0 1 0 0 0
4 4 0 1 1 0 0 0 0
5 5 1 0 0 0 0 0 0
6 6 0 1 0 0 0 0 0
7 7 0 1 0 0 0 0 0
8 8 0 1 0 1 0 0 0
9 9 1 0 0 0 0 0 0
10 10 1 0 0 0 0 0 1
我的工作流程要求我知道一系列变量到虚拟代码(即gender:like_product
),但不想手动识别每个变量(可能有数百个变量)。同样,我不希望必须将每个变量的每个级别/唯一值标识为伪代码。我最终正在寻找tidyverse
解决方案。
我知道有几种方法可以做到这一点,但是没有一种方法可以完美地适应整齐。我知道我可以使用mutate ......
tib %>%
mutate(gender_M = ifelse(gender == "M", 1, 0),
gender_F = ifelse(gender == "F", 1, 0),
like_product_1 = ifelse(like_product == 1, 1, 0),
like_product_2 = ifelse(like_product == 2, 1, 0),
like_product_3 = ifelse(like_product == 3, 1, 0),
like_product_4 = ifelse(like_product == 4, 1, 0),
like_product_5 = ifelse(like_product == 5, 1, 0)) %>%
select(-gender, -like_product)
但这会破坏我需要指定每个虚拟编码输出的工作流程规则。
我以前使用stats
包中的model.matrix完成了这项工作。
model.matrix(~ gender + like_product, tib)
简单明了,但我希望在tidyverse中找到解决方案。 编辑:原因是,我仍然必须指定每个变量,并且能够使用选择帮助程序来指定类似gender:like_product
的内容将更受欢迎。
我认为解决方案在purrr
library(purrr)
dummy_code <- function(x) {
lvls <- levels(x)
sapply(lvls, function(y) as.integer(x == y)) %>% as.tibble
}
tib %>%
map_at(c("gender", "like_product"), dummy_code)
$record
[1] 1 2 3 4 5 6 7 8 9 10
$gender
# A tibble: 10 x 2
F M
<int> <int>
1 1 0
2 0 1
3 0 1
4 1 0
5 1 0
6 0 1
7 1 0
8 0 1
9 1 0
10 0 1
$like_product
# A tibble: 10 x 5
`1` `2` `3` `4` `5`
<int> <int> <int> <int> <int>
1 0 1 0 0 0
2 1 0 0 0 0
3 0 1 0 0 0
4 0 0 1 0 0
5 0 0 0 1 0
6 0 1 0 0 0
7 0 0 0 1 0
8 0 0 0 1 0
9 0 0 0 1 0
10 0 0 0 0 1
这个尝试会产生一个包含排序变量record
的异常列表,而且我将它们全部组合成一个单独的tibble是不成功的。此外,我仍然需要指定每一列,总体来说它看起来很笨重。
有更好的想法吗?谢谢!
答案 0 :(得分:3)
model.matrix
的替代方法是使用包recipes
。这仍然是一项正在进行中的工作,尚未包括在tidyverse中。在某些时候,它可能/将被包含在tidyverse packages中。
我会留给您阅读食谱,但在步骤step_dummy
中,您可以使用tidyselect
包中的特殊选择器(与recipes
一起安装),例如选择器您可以在dplyr
中使用starts_with()
。我创建了一个小例子来展示步骤。
以下示例代码。
但如果这更方便,我会留下你,因为评论中已经指出了这一点。函数bake()
使用model.matrix来创建假人。差异主要在于列名,当然也包括在所有单独步骤的基础代码中进行的内部检查。
library(recipes)
library(tibble)
tib <- as.tibble(list(record = c(1:10),
gender = as.factor(sample(c("M", "F"), 10, replace = TRUE)),
like_product = as.factor(sample(1:5, 10, replace = TRUE))))
dum <- tib %>%
recipe(~ .) %>%
step_dummy(gender, like_product) %>%
prep(training = tib) %>%
bake(newdata = tib)
dum
# A tibble: 10 x 6
record gender_M like_product_X2 like_product_X3 like_product_X4 like_product_X5
<int> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 1. 1. 0. 0. 0.
2 2 1. 1. 0. 0. 0.
3 3 1. 1. 0. 0. 0.
4 4 0. 0. 1. 0. 0.
5 5 0. 0. 0. 0. 0.
6 6 0. 1. 0. 0. 0.
7 7 0. 1. 0. 0. 0.
8 8 0. 0. 0. 1. 0.
9 9 0. 0. 0. 0. 1.
10 10 1. 0. 0. 0. 0.