从互斥虚拟变量创建分类变量

9
我的问题是关于之前回答过的一个问题的详细说明,该问题涉及将多个虚拟变量合并为单个分类变量的组合
在以前提出的问题中,分类变量是从不互斥的虚拟变量创建的。对于我的情况,我的虚拟变量是互斥的,因为它们代表了2X2受试者间因子设计交叉实验条件(也有一个我这里不涉及的受试者内部分量),所以我不认为interaction可以满足我的需求。
例如,我的数据可能是这样的:
id   conditionA    conditionB    conditionC     conditionD
1    NA            1             NA             NA
2    1             NA            NA             NA
3    NA            NA            1              NA
4    NA            NA            NA             1
5    NA            2             NA             NA
6    2             NA            NA             NA
7    NA            NA            2              NA
8    NA            NA            NA             2

我希望现在可以创建跨不同类型条件的分类变量。例如,对于具有条件A和B值的人可以编码为一个分类变量,对于具有条件C和D值的人也是如此。
id   conditionA    conditionB    conditionC     conditionD  factor1    factor2
1    NA            1             NA             NA          1          NA
2    1             NA            NA             NA          1          NA
3    NA            NA            1              NA          NA         1
4    NA            NA            NA             1           NA         1
5    NA            2             NA             NA          2          NA
6    2             NA            NA             NA          2          NA
7    NA            NA            2              NA          NA         2
8    NA            NA            NA             2           NA         2

我现在是使用ifelse()语句来实现这个功能的,但这种方法非常混乱(并且不总是有效)。请帮忙!可能有一些超级明显的“更容易”的方法。

编辑:

我正在使用的ifelse命令如下:

attach(df)
df$factor<-ifelse(conditionA==1 | conditionB==1, 1, NA)
df$factor<-ifelse(conditionA==2 | conditionB==2, 2, df$factor)

实际上,每次我都要跨越6-8列进行合并,因此更优雅的解决方案会帮助很多。

3个回答

6

更新(2019年):请使用 dplyr :: coalesce(),其工作方式基本相同。

我的R包有一个便利函数,允许选择列表中每个元素的第一个非NA值:

#library(devtools)
#install_github('kimisc', 'muelleki')
library(kimisc)

df$factor1 <- with(df, coalesce.na(conditionA, conditionB))

如果conditionAconditionB是因子,则不确定此方法是否有效。如有必要,请在使用as.numeric(as.character(...))之前将它们转换为数字。

否则,您可以尝试使用interaction,结合重新编码结果因子的级别 - 但在我看来,您更感兴趣的是第一种解决方案:

df$conditionAB <- with(df, interaction(coalesce.na(conditionA, 0), 
                                       coalesce.na(conditionB, 0)))
levels(df$conditionAB) <- c('A', 'B')

谢谢!干得好...当我制作示例数据时,最后两行有一个打字错误。 - roody
@roody:conditionD 是否可能包含值,比如说 3?那么应该发生什么? - krlmlr
不,它们都是二级因子变量——1和2只是Qualtrics分配给它们的值,但它总是二元选择。 - roody
嗨 - 我已添加更多示例。不过 R 不允许我安装您的包。它给出了一个错误,显示 sh: make: command not found ERROR: compilation failed for package 'kimisc' - roody
1
@roody:你是在Windows上吗?那么你可能需要安装Rtools。否则,安装GNU工具链(makeg++,...)。或者直接从这里复制代码... - krlmlr
1
@roody,另一种感谢的方式是点赞有帮助的答案。 - Arun

1

嗯,我认为你可以简单地使用ifelse来完成,就像这样:

factor1 <- ifelse(is.na(conditionA), conditionB, conditionA)

Another way could be :

factor1 <- conditionA
factor1[is.na(factor1)] <- conditionB

第三种解决方案,如果您有超过两个列条件,那么肯定更实用:

factor1 <- apply(df[,c("conditionA","conditionB")], 1, sum, na.rm=TRUE)

嗨@juba--我喜欢第三种解决方案的简洁性...但是如果R将它们读入因子,我该如何将所有相关列更改为数字?当cols是列号列表时,命令df[cols] <- as.numeric(as.matrix(df[cols]))似乎不起作用。 - roody

1

我认为这个函数可以提供你需要的东西(诚然,这只是一个快速的hack)。

to_indicator <- function(x, grp)
{
    apply(tbl, 1,
          function (x)
          {
              idx <- which(!is.na(x))
              nm <- names(idx)
              if (nm %in% grp)
                x[idx]
              else
                NA
          })
}

这是它与您提供的示例数据一起使用的方式。
tbl <- read.table(header=TRUE, text="
conditionA    conditionB    conditionC     conditionD
NA            1             NA             NA
1             NA            NA             NA
NA            NA            1              NA
NA            NA            NA             1
NA            2             NA             NA
2             NA            NA             NA
NA            NA            2              NA
NA            NA            NA             2")
tbl <- data.frame(tbl)

(tbl <- cbind(tbl,
              factor1=to_indicator(tbl, c("conditionA", "conditionB")),
              factor2=to_indicator(tbl, c("conditionC", "conditionD"))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接