2015-03-02 128 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