2016-06-20 72 views
0

我是一個R(和編碼新手)一行,我正在尋找一種方式來重新配置下面的表A顯示爲表B.如何表格數據重塑每

表A

type x1 x2 x3 
A  4 6 9 
A  7 4 1 
A  9 6 2 
B  1 3 8 
B  2 7 9 

我找的代碼,將轉換爲以下

表B

type x1 x2 x3 x1' x2' x3' x1'' x2'' x3'' 
A  4 6 9 7 4 1 9  6 2 
B  1 3 8 2 7 9 

實表A超過150000行和36列。具有2100個獨特的「類型」值。

感謝您的幫助。

-Shawn

+0

歡迎的StackOverflow!我注意到Vector B是多維的,所以這就是我們所說的R語言中的data.frame或矩陣。你是這個意思嗎?或者你想要3個獨立的載體? –

+0

我們也可以調用Vector B a Matrix。我編輯了原始問題,使其更加清晰。謝謝! – SDM1212

+1

當然。我做了一個特別的解決方案,然後我們受到了無評論的惡魔怪獸的攻擊,所以我不得不刪除它。如果你的數據很大或者你需要做很多工作,我們應該找到一個更加程序化的解決方案。唯一真正的困難是,在這種格式中,我們需要爲缺失的B單元格添加NA。因此,我認爲通過'for'循環,'cbind'和'rbind'使用'fill = T'是一種方法去。 –

回答

3

對我來說,這個解決方案看起來很漂亮簡單

# split the data frame by type and use unlist, which will provide names 
ld <- lapply(split(d[-1], d[["type"]]), unlist) 

# gather all the unique names in the list 
ldNames <- Reduce(unique, lapply(ld, names)) 

# use the names to index each list element, which makes them 
# all of equal length and suitable for row binding. 
do.call(rbind, lapply(ld, function(x) x[ldNames])) 
# x11 x12 x13 x21 x22 x23 x31 x32 x33 
# A 4 7 9 6 4 6 9 1 2 
# B 1 2 NA 3 7 NA 8 9 NA 

如果上面的輸出順序不理想,還可以重新排列:

# save the output from above 
d2 <- do.call(rbind, lapply(ld, function(x) x[ldNames])) 
# reorder the names 
ldNames_sorted <- c(matrix(ldNames, ncol = (ncol(d) - 1), byrow = TRUE)) 

# apply the new order. 
d2 <- d2[, ldNames_sorted] 
# x11 x21 x31 x12 x22 x32 x13 x23 x33 
#A 4 6 9 7 4 1 9 6 2 
#B 1 3 8 2 7 9 NA NA NA 

要爲類型,而不是使用行名增加一列,一個方法是:

data.frame(type = row.names(d2), d2) 
+2

相當像結合'lapply'和'split'的方法。大! (+1)。然而,B的最終輸出與問題不符,可以更新解決方案;) – Patric

+0

最後一個問題。我們需要具有「類型」的列具有列標題。 – SDM1212

+0

@ SDM1212我在最後添加了一個最後一行來添加一個'type'列。希望有所幫助! – Jota

1

拿一個嘗試,解決的辦法是不是這樣簡潔,只是給你一個hint.I覺得很多事情可以得到改善。

但最後,我們必須在這裏@引進來港:(

zz <- "type x1 x2 x3 
A  4 6 9 
A  7 4 1 
A  9 6 2 
B  1 3 8 
B  2 7 9" 

dA <- read.table(text=zz, header=T) 


tmp<-(sapply(unique(dA$type), FUN=function(x) as.vector(t(dA[dA$type == x, -1])))) 

t(sapply(tmp, '[', seq(max(sapply(tmp, length))))) 
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 4 6 9 7 4 1 9 6 2 
[2,] 1 3 8 2 7 9 NA NA NA 
1
a <- data.frame(type=c("A", "A","A", "B", "B"), x1 = c(4,7,9,1,2),x2=c(6,4,6,3,7), 
       x3 = c(9,1,2,8,9)) 

library(dplyr) 
tmp <- 
a %>% 
    group_by(type) %>% 
    summarise(no_rows = length(type)) 

for(i in unique(a$type)){ 
    n <- max(tmp$no_rows) - nrow(a[a$type == i,]) 
    nn <- nrow(a) 
    if(n > 0){ 
    for(ii in 1:n){ 
     a[nn+ii,] <- c(i,NA,NA,NA) 
    }  
    } 

} 

a <- a[order(a$type),] 
a$timevar <- seq(1:max(tmp$no_rows)) 

b<-reshape(a,timevar="timevar",idvar="type",direction="wide",drop = F) 
b 

    type x1.1 x2.1 x3.1 x1.2 x2.2 x3.2 x1.3 x2.3 x3.3 
1 A 4 6 9 7 4 1 9 6 2 
4 B 1 3 8 2 7 9 <NA> <NA> <NA> 
+0

我認爲你的邏輯是合理的,但它可以簡化一點點。看到我的答案,我認爲做同樣的事情(我認爲 - 這是一個看似困難的問題) – thelatemail

+0

@thelatemail我毫不懷疑你是對的。我會+1你的回答 –

1

變化哈克-R的回答是:

A$num <- with(A, ave(as.character(type), type, FUN=seq_along)) 
tmp <- cbind(A[c(1,5)], stack(A[2:4])) 
tmp$time <- paste(tmp$ind, tmp$num, sep=".") 

reshape(tmp[c("type","time","values")], idvar="type", timevar="time", direction="wide") 

# type values.x1.1 values.x1.2 values.x1.3 values.x2.1 values.x2.2 values.x2.3 values.x3.1 values.x3.2 values.x3.3 
#1 A   4   7   9   6   4   6   9   1   2 
#4 B   1   2   NA   3   7   NA   8   9   NA 

而一個dplyr版本的樂趣:

library(dplyr) 
library(tidyr) 

A %>% 
    gather(var, value, -type) %>% 
    group_by(type,var) %>% 
    mutate(time=seq_along(var)) %>% 
    ungroup() %>% 
    unite(grpvar, c(time,var)) %>% 
    spread(grpvar, value) 

#Source: local data frame [2 x 10] 
# 
# type 1_x1 1_x2 1_x3 2_x1 2_x2 2_x3 3_x1 3_x2 3_x3 
# (chr) (int) (int) (int) (int) (int) (int) (int) (int) (int) 
#1  A  4  6  9  7  4  1  9  6  2 
#2  B  1  3  8  2  7  9 NA NA NA 
+0

嗨 - 我不確定如何使用@ Hack-R的答案。 – SDM1212

+0

@ SDM1212 - 基於Hack-R的邏輯,這是一個完全的答案。你不必與其他任何東西一起使用它。 – thelatemail

+0

好吧,我開始明白了,我得到了運行的例子。所以對於真實的數據obs的數量。將會改變,但總是會有22個變量。我不知道如何改變這個例子來處理我的真實數據。 – SDM1212

2

晚會有點晚,但這也可以用data.table包的dcast功能輕鬆完成,因爲您可以使用多個value.var的它:

library(data.table) 

dcast(setDT(d), type ~ rowid(type), value.var = c('x1','x2','x3'), sep = '') 

這給:

type x11 x12 x13 x21 x22 x23 x31 x32 x33 
1: A 4 7 9 6 4 6 9 1 2 
2: B 1 2 NA 3 7 NA 8 9 NA 

您也可以做到這一點的基礎R:

d$num <- ave(d$x1, d$type, FUN = seq_along) 
reshape(d, idvar = 'type', direction = 'wide', timevar = 'num', sep = '')