首页 > 解决方案 > 使用 mutate_at() 从单个变量的值创建多个二进制变量

问题描述

我有一些包含以下支持值 {a, b, c, ... k} 的变量,我想为每个响应创建多个二进制变量。例如,var_a将等同于as.numeric(变量名很长== "a")var_b将等同于as.numeric(变量名很长== "b")等等。然而,在某些变量中,它们并没有从 a:k 整齐地走出来。有些人可能跳过了一两个字母。

当我有多个要更改的变量时,我知道如何使用 mutate_at,但是如果我只有一个变量要同时创建多个变量怎么办?

到目前为止,我一直在做的是:

df <- df %>% mutate(var_a = as.numeric(`variable name very long` == "a"),
                    var_b = as.numeric(`variable name very long` == "b"),
                    ...)

当然,我要创建的变量不止两个。有没有更简单的方法来做到这一点?而且我还使用 mutate 作为缩短变量名的方法。我还尝试创建一个函数,它可能能够为我想要的任何变量和值执行此操作,因为我必须经常这样做,但我无法让它工作:

varname <- function(newvar, var, value){
           df <- df %>% mutate(newvar = as.numeric(var == "value"))
}

varname("var_a", "`variable name very long`", "a")

任何建议都深表感谢。谢谢!

标签: rfunctiondplyr

解决方案


我们可以使用map2循环unique列中的元素以及vector新列名transmute来创建列,并将输出与原始数据绑定

library(dplyr)
library(purrr)
library(stringr)
un1 <- sort(as.character(unique(df[["variable name very long"]])))
un2 <- str_c('var_', un1)
map2_dfc(un1, un2, ~ df %>%

                       transmute(!! .y :=  +(`variable name very long` == .x))) %>%
       bind_cols(df, .)
# A tibble: 20 x 7
#   `variable name very long`     val var_a var_b var_c var_d var_e
# * <chr>                       <dbl> <int> <int> <int> <int> <int>
# 1 c                         -0.710      0     0     1     0     0
# 2 b                         -1.04       0     1     0     0     0
# 3 c                         -0.798      0     0     1     0     0
# 4 e                          0.319      0     0     0     0     1
# 5 b                          1.87       0     1     0     0     0
# 6 b                         -0.317      0     1     0     0     0
# 7 a                         -0.773      1     0     0     0     0
# 8 d                         -1.44       0     0     0     1     0
# 9 a                         -0.348      1     0     0     0     0
#10 a                         -0.421      1     0     0     0     0
#11 e                          1.06       0     0     0     0     1
#12 e                          0.528      0     0     0     0     1
#13 a                          3.13       1     0     0     0     0
#14 e                         -0.546      0     0     0     0     1
#15 e                         -1.05       0     0     0     0     1
#16 d                         -0.687      0     0     0     1     0
#17 e                         -1.13       0     0     0     0     1
#18 b                         -0.489      0     1     0     0     0
#19 a                          1.85       1     0     0     0     0
#20 d                         -0.0376     0     0     0     1     0

或者另一种选择是pivot_wider

library(tidyr)
df %>%
   mutate(rn = row_number(), n = 1,
         newcol = str_c('var_', `variable name very long`)) %>% 
   pivot_wider(names_from = newcol, values_from = n, values_fill = list(n = 0))

base Rmodel.matrix

cbind(df, model.matrix(~ `variable name very long` -1, df))

数据

set.seed(24)
df <- tibble(`variable name very long` = sample(letters[1:5],
      20, replace = TRUE), val = rnorm(20))

推荐阅读