将管道分隔的单列数据转换为多列矩阵-R

时间:2013-06-04 02:40:50

标签: 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

我希望有一种比我冗长的代码更简单的方法。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分: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)