2014-01-06 29 views
2

我有三個因素,其中兩個是二進制的,第三個是整數數據框:如何在R中爲多維構建二進制數據框架?

 DATA YEAR1 YEAR2 REGION1 REGION2 
OBS1 X  1  0  1   0 
OBS2 Y  1  0  0   1 
OBS3 Z  0  1  1   0 

現在我想將它轉換爲這樣的事情

 YEAR1_REGION1 YEAR1_REGION2 YEAR2_REGION1 YEAR2_REGION2 
OBS1 X    0    0    0 
OBS2 0    Y    0    0 
OBS3 0    0    Z    0 

基本矩陣乘法不是我所追求的。我想找到一個簡單的方法來做到這一點,並自動將列重命名。我的實際數據有三個因子維度,包含20 * 8 * 6個觀察值,所以最終總共會有960列。

回答

4

以下是另一種基於outer和類似於@Roland答案的方法。

year <- grep("YEAR", names(DF), value = TRUE) 
region <- grep("REGION", names(DF), value = TRUE) 
data <- as.character(DF$DATA) 

df <- outer(year, region, function(x, y) DF[,x] * DF[,y]) 
colnames(df) <- outer(year, region, paste, sep = "_") 
df <- as.data.frame(df) 

for (i in seq_len(ncol(df))) 
    df[as.logical(df[,i]), i] <- data[as.logical(df[,i])] 

df 
##  YEAR1_REGION1 YEAR2_REGION1 YEAR1_REGION2 YEAR2_REGION2 
## OBS1    X    0    0    0 
## OBS2    0    0    Y    0 
## OBS3    0    Z    0    0 
4

也許別人會拿出一個更簡潔的可能性,但是這創造了預期的結果:

DF <- read.table(text="  DATA YEAR1 YEAR2 REGION1 REGION2 
OBS1 X  1  0  1   0 
OBS2 Y  1  0  0   1 
OBS3 Z  0  1  1   0", header=TRUE) 

DF[,-1] <- lapply(DF[,-1], as.logical) 
DF[,1] <- as.character(DF[,1]) 

res <- apply(expand.grid(2:3, 4:5), 1, function(i) { 
    tmp <- rep("0", length(DF[,1])) 
    ind <- do.call(`&`,DF[,i]) 
    tmp[ind] <- DF[ind,1] 
    tmp <- list(tmp) 
    names(tmp) <- paste0(names(DF)[i], collapse="_") 
    tmp 
}) 

res <- as.data.frame(res) 
rownames(res) <- rownames(DF) 


#  YEAR1_REGION1 YEAR2_REGION1 YEAR1_REGION2 YEAR2_REGION2 
# OBS1    X    0    0    0 
# OBS2    0    0    Y    0 
# OBS3    0    Z    0    0 

然而,我懷疑有一個更好的可能性,以實現你真正想做的事,而無需創建一個巨大的寬幅數據幀。

相關問題