2

我需要一些关于 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

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)
于 2013-06-04T03:23:34.807 回答