2015-03-02 100 views
3

我有一个数据集,其中一些分类变量被转换为虚拟变量(所有类使用,不是n-1),有些不是。我试图在一列中重新编码它们。R撤销虚拟变量

例如

Q1.1 Q1.2 Q1.3 Q1.NA Q2 Q3.1 Q3.2 
1  0  0  0  3  0  1 
0  1  0  0  4  1  0 
0  0  1  0  2  0  1 

有没有一种简单的方法将其转换为:

Q1  Q2  Q3 
1  3  2 
2  4  1  
3  2  2 

现在我只是用strsplit()(所有空置的变量名包含'.')与情侣循环,但觉得应该有更好的方法。有什么建议么?

+0

应该'Q3'是'2,1,3' – akrun 2015-03-02 16:34:08

+0

@akrun:不要这么认为 - 有3个问题,Q1和Q3是空置的。 Q1有1,2,3级; Q3有1,2级。 – screechOwl 2015-03-02 16:36:24

+0

好的,我在考虑'1'的位置 – akrun 2015-03-02 16:37:51

回答

0

我写了一个函数,然后做了这样的事情。

MultChoiceCondense<-function(vars,indata){ 
    tempvar<-matrix(NaN,ncol=1,nrow=length(indata[,1])) 
    dat<-indata[,vars] 
    for (i in 1:length(vars)){ 
    for (j in 1:length(indata[,1])){ 
     if (dat[j,i]==1) tempvar[j]=i 
    } 
    } 
    return(tempvar) 
} 

如果你的数据被称为Dat,则:

Dat$Q1<-MultChoiceCondense(c("Q1.1","Q1.2","Q1.3"),Dat) 
1

下面是一个使用从 “reshape2” meltcSplit从我的 “splitstackshape” 包一些 “data.table” 好玩一起的方法。我已经加载了dplyr,这样我们就可以管好所有的东西。

library(splitstackshape) 
library(reshape2) 
library(dplyr) 

mydf %>% 
    as.data.table(keep.rownames = TRUE) %>%  # Convert to data.table. Keep rownames 
    melt(id.vars = "rn", variable.name = "V") %>% # Melt the dataset by rownames 
    .[value > 0] %>%        # Subset for all non-zero values 
    cSplit("V", ".") %>%       # Split the "V" column (names) by "." 
    .[is.na(V_2), V_2 := value] %>%    # Replace NA values with actual values 
    dcast.data.table(rn ~ V_1, value.var = "V_2") # Go wide. 
# rn Q1 Q2 Q3 
# 1: 1 1 3 2 
# 2: 2 2 4 1 
# 3: 3 3 2 2 

这里是一个可能的基础R方法:

## Which columns are binary? 
Bins <- sapply(mydf, function(x) { 
    all(x %in% c(0, 1)) 
}) 

## Two vectors -- part after the dot and before 
X <- gsub(".*\\.(.*)$", "\\1", names(mydf)[Bins]) 
Y <- unique(gsub("(.*)\\..*$", "\\1", names(mydf)[Bins])) 

## Use `apply` to subset the X value based on the 
## logical version of the binary variable 
cbind(mydf[!Bins], 
     `colnames<-`(t(apply(mydf[Bins], 1, function(z) { 
     X[as.logical(z)] 
     })), Y)) 
# Q2 Q1 Q3 
# 1 3 1 2 
# 2 4 2 1 
# 3 2 3 2 

最后,你可以重新排序的列必需的。您可能还需要将它们转换为数字,因为在这种情况下,Q1和Q3将是因素。

0

另一个基础R方法

dat <- read.table(header = TRUE, text = "Q1.1 Q1.2 Q1.3 Q1.NA Q2 Q3.1 Q3.2 
1  0  0  0  3  0  1 
0  1  0  0  4  1  0 
0  0  1  0  2  0  1") 

## this will take all the unique questions; Q1, Q2, Q3; test if 
## they are dummies; and return the column if so or find which 
## dummy column is a 1 otherwise 
res <- lapply(unique(gsub('\\..*', '', names(dat))), function(x) { 
    tmp <- dat[, grep(x, names(dat)), drop = FALSE] 
    if (ncol(tmp) == 1) unlist(tmp, use.names = FALSE) else max.col(tmp) 
    }) 

# [[1]] 
# [1] 1 2 3 
# 
# [[2]] 
# [1] 3 4 2 
# 
# [[3]] 
# [1] 2 1 2 

do.call('cbind', res) 
#  [,1] [,2] [,3] 
# [1,] 1 3 2 
# [2,] 2 4 1 
# [3,] 3 2 2