【问题标题】:Creating dummy variables in tidyverse syntax?在 tidyverse 语法中创建虚拟变量?
【发布时间】:2021-09-17 23:41:00
【问题描述】:

我有一个像这样的数据框:

dat <- tribble(
  ~isHot, ~isCrispy, ~Restaurant,
  1, 0, "A",
  0, 0, "B",
  1, 1, "B",
  0, 0, "C"
)

> dat
# A tibble: 4 × 3
  isHot isCrispy Restaurant
  <dbl>    <dbl> <chr>     
1     1        0 A         
2     0        0 B         
3     1        1 B         
4     0        0 C    

我想为所有分类变量创建虚拟变量以获得以下输出:

  isHot isCrispy Restaurant_A Restuarant_B     
1     1        0 1            0
2     0        0 0            1
3     1        1 0            1
4     0        0 0            0

我可以通过 tidyverse 语法做到这一点吗?我不想使用recipesfastdummies 或其他包。

编辑:

我希望代码适用于所有分类变量。在这个例子中,只有一个分类变量,但如果还有更多呢? 我希望能够采用特征名称并创建假人。 例如,如果有另一个名为 City 的分类特征,我会有虚拟变量,如..City_A、City_B 等。

【问题讨论】:

  • 你为什么要那个?如果要执行回归,则无需显式构建模型矩阵。首先。 lm(y ~ ., dat) 就足够了。

标签: r


【解决方案1】:

这是dpylr的一种方法

dat %>%
  mutate(k = paste0("Restaurant_", Restaurant), v = 1) %>%
  pivot_wider(names_from = k, values_from = v, values_fill = 0) %>%
  select(-Restaurant)

【讨论】:

  • 其实你也在用tidyr(来自pivot_wider)。
  • 我怎样才能对所有分类变量执行此操作?在我的示例中,只有一个分类变量,但我怎样才能使代码动态地适用于所有人?
【解决方案2】:

dplyr

根据要求,

library(dplyr)
library(tidyr) # pivot_wider
dat %>%
  mutate(rn = row_number(), val = 1L) %>%
  pivot_wider(c("rn", "isHot", "isCrispy"),
    names_from = "Restaurant", values_from = "val",
    names_prefix = "Restaurant_", values_fill = 0L) %>%
  select(-rn)
# # A tibble: 4 x 5
#   isHot isCrispy Restaurant_A Restaurant_B Restaurant_C
#   <dbl>    <dbl>        <int>        <int>        <int>
# 1     1        0            1            0            0
# 2     0        0            0            1            0
# 3     1        1            0            1            0
# 4     0        0            0            0            1

但这似乎比它需要的更复杂......

基础 R

model.matrix(~ 0 + Restaurant, data = dat)
#   RestaurantA RestaurantB RestaurantC
# 1           1           0           0
# 2           0           1           0
# 3           0           1           0
# 4           0           0           1
# attr(,"assign")
# [1] 1 1 1
# attr(,"contrasts")
# attr(,"contrasts")$Restaurant
# [1] "contr.treatment"

这导致 dplyr-ification 为

dat %>%
  mutate(as.data.frame(model.matrix(~ 0 + Restaurant, data = cur_data()))) %>%
  select(-Restaurant)
# # A tibble: 4 x 5
#   isHot isCrispy RestaurantA RestaurantB RestaurantC
#   <dbl>    <dbl>       <dbl>       <dbl>       <dbl>
# 1     1        0           1           0           0
# 2     0        0           0           1           0
# 3     1        1           0           1           0
# 4     0        0           0           0           1

编辑您的“动态因素”请求。由于您没有更新示例数据,我将添加一列:

dat$QUUX <- c("x","x","y","y")

isfac <- sapply(dat, inherits, c("character", "factor"))
isfac
#      isHot   isCrispy Restaurant       QUUX 
#      FALSE      FALSE       TRUE       TRUE 

out <- do.call(cbind, c(list(dat), lapply(paste("~ 0 +", names(isfac)[isfac]), function(frm) model.matrix(formula(frm), data = dat))))
out[, !names(out) %in% names(isfac)[isfac]]
#   isHot isCrispy RestaurantA RestaurantB RestaurantC QUUXx QUUXy
# 1     1        0           1           0           0     1     0
# 2     0        0           0           1           0     1     0
# 3     1        1           0           1           0     0     1
# 4     0        0           0           0           1     0     1

【讨论】:

  • 感谢您的解决方案,我刚刚更新了我的问题。我希望它对所有分类变量都是动态的。
  • 这很棒。你有通过 dplyr 的解决方案吗?
  • 不是临时的,这个解决方案不能使用有什么原因吗?并非所有东西都需要“整洁”才能有用和充分:-)
  • 我只是想知道这个解决方案很好。需要弄清楚如何删除具有超过 2 个唯一值的特征的 1 列。因为会有一个参考。
猜你喜欢
  • 2019-11-09
  • 2020-06-18
  • 2023-03-27
  • 2017-04-23
  • 2023-03-24
  • 1970-01-01
  • 2018-04-06
  • 2020-01-31
  • 1970-01-01
相关资源
最近更新 更多