2013-06-04 62 views
2

我需要一些在R中進行數據操作的幫助。我有一個很長的代碼,它將這作爲一系列步驟來完成,但我正在尋找一種更短的方法來執行它。將管道分隔的單列數據轉換爲多列矩陣 - R

這裏是具有兩列的數據幀 - 第一個是一個ID和如下所示的其它已管道分隔在其數據:

ID DATA 
1 a 
2 a|b 
3 b|c 
4 d|e 

我需要將此轉換爲這種形式:

ID a b c d e 
1 1 0 0 0 0 
2 1 1 0 0 0 
3 0 1 1 0 0 
4 0 0 0 1 1 

我希望有一個比我冗長的代碼更簡單的方法來做到這一點。

在此先感謝您的幫助。

回答

4

這適用於提供的數據。首先讀取數據:

pipdat <- read.table(stdin(),header=TRUE,stringsAsFactors=FALSE) 
ID DATA 
1 a 
2 a|b 
3 b|c 
4 d|e 

# leave a blank line at the end so it stops reading 

現在這裏有雲:

nr <- dim(pipdat)[1] 
chrs <- strsplit(pipdat[,2],"[|]") 
af <- unique(unlist(chrs)) 
whichlet <- function(a,fac) as.numeric(fac %in% a) 
matrix(unlist(lapply(chrs,whichlet,af)), 
     byrow=TRUE,nr=nr,dimnames=list(ID=1:nr,af)) 

(也可在更少的行來完成,但它很方便的看到其中的一些步驟做)

它產生:

ID a b c d e 
    1 1 0 0 0 0 
    2 1 1 0 0 0 
    3 0 1 1 0 0 
    4 0 0 0 1 1 

我從你的帖子猜測你想要ID作爲行名;如果你需要它是最後一行需要不同的數據列。

我會使用sapply而不是lapply,但最終會得到所需矩陣的轉置。如果你用最後一行替換:

res <- t(sapply(chrs,whichlet,af)) 
dimnames(res) <- list(ID=1:nr,af) 
res 

但它可能會變慢。

---

如果你不遵守行

matrix(unlist(lapply(chrs,whichlet,af)), 
     byrow=TRUE,nr=nr,dimnames=list(ID=1:nr,af)) 

只是從最裏面的功能向外打破它:

lres <- lapply(chrs,whichlet,af) 
vres <- unlist(lres) 
matrix(vres,byrow=TRUE,nr=nr,dimnames=list(ID=1:nr,af)) 

---

如果您需要將ID作爲數據列而不是行名,則可以採用以下方法之一:

lres <- lapply(chrs,whichlet,af) 
vres <- unlist(lres) 
cbind(ID=1:nr,matrix(vres,byrow=TRUE,nr=nr,dimnames=list(1:nr,af))) 

,或者你可以做

res <- t(sapply(chrs,whichlet,af)) 
dimnames(res) <- list(1:nr,af) 
cbind(ID=1:nr,res) 
+0

輝煌 - 謝謝!我會花一些時間和理解你的最後一行 - 但我肯定會。 – 2013-06-04 03:34:07

+0

查看對我的答案的更改,這可能會解釋更多 - 無論是作爲行名的ID的註釋還是關於最後一行的末尾部分。 –

+0

對遲交的道歉。但是,再次感謝。我只是按照你的代碼學習了一噸R。 –