在dplyr链中创建指标变量列

Tom*_*Tom 8 r dplyr tidyr

更新:对于那些回复的人道歉,在我最初的例子中,我忽略了作为一个因素data.frame()创建的事实,var而不是像我想象的那样作为一个角色向量.我已经纠正了这个例子,这将至少打破其中一个答案.

- 原版的 -

我有一个数据框,我正在执行一系列dplyrtidyr操作,我想为指标变量添加列,编码为0或1,并在dplyr链中执行此操作.因子的每个级别(当前存储为字符向量)应该在单独的列中编码,并且列名称是固定前缀与变量级别的串联,例如var具有级别a,新列var_a将是1,以及所有其他级别行将为var_a0.

下面使用基数R的最小例子产生了我想要的结果(感谢这篇博文),但我想将它全部卷入dplyr链,并且无法弄清楚如何做到这一点.

library(dplyr)
df <- data.frame(var = sample(x = letters[1:4], size = 10, replace = TRUE), stringsAsFactors = FALSE)
for(level in unique(df$var)){
  df[paste("var", level, sep = "_")] <- ifelse(df$var == level, 1, 0)
}
Run Code Online (Sandbox Code Playgroud)

请注意,实际数据集包含多个列,创建指示符变量时不应更改或删除任何列,但列var可以转换为类型因子.

MrF*_*ick 5

它不漂亮,但这个功能应该有效

dummy <- function(data, col) {
    for(c in col) {
        idx <- which(names(data)==c)
        v <- data[[idx]]
        stopifnot(class(v)=="factor")
        m <- matrix(0, nrow=nrow(data), ncol=nlevels(v))
        m[cbind(seq_along(v), as.integer(v))]<-1
        colnames(m) <- paste(c, levels(v), sep="_")
        r <- data.frame(m)
        if ( idx>1 ) {
            r <- cbind(data[1:(idx-1)],r)
        }
        if ( idx<ncol(data) ) {
            r <- cbind(r, data[(idx+1):ncol(data)])
        }
        data <- r
    }
    data
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例data.frame

dd <- data.frame(a=runif(30),
    b=sample(letters[1:3],30,replace=T),
    c=rnorm(30),
    d=sample(letters[10:13],30,replace=T)
)
Run Code Online (Sandbox Code Playgroud)

并指定要作为字符向量展开的列.你可以做

dd %>% dummy("b")
Run Code Online (Sandbox Code Playgroud)

要么

dd %>% dummy(c("b","d"))
Run Code Online (Sandbox Code Playgroud)