R中的data.frame:一对多转换一对一?

时间:2014-04-04 19:58:50

标签: r

原始data.frame:

UniProt.ID         Drug.IDs
1     P45059          DB00303
2     P19113 DB00114; DB00117

我想将其更改如下:

UniProt.ID         Drug.IDs
1     P45059          DB00303
2     P19113          DB00114
3     P19113          DB00117  
如果我有很多行,你有更好更有效的方法吗? 感谢。

凯文

3 个答案:

答案 0 :(得分:1)

我完全清楚这可能有点矫枉过正,并且有一种更简单的方法。但这似乎是一个可能最好用自制功能解决的问题。这是一个我希望能在您的完整数据集上工作的人。当我添加的数据超过你在帖子中提供的数据时,它可以在我的最终工作。

这些数据自然被R强制转化为factor课程。

UniProt.ID <- c("P45059", "P19113 DB00114;",
                "P57809", "P21548 DB00954;",
                "P48502", "P18456 DB49785;")
Drug.IDs <- c("DB00303", "DB00117", "DB34658")
data2 <- data.frame(UniProt.ID, Drug.IDs)

功能。

colSplitter <- function(data)
  {
    d <- sapply(data, as.character)
    minChar <- min(sapply(d[,1], nchar))
    new <- sapply(1:nrow(d), function(i){
      if(nchar(d[i, 1]) > minChar){
        newD2 <- gsub(".*\\s|;", "", d[i,1])
        newD1 <- gsub("\\s.*", "", d[i,1])
        rbind(d[i-1, ], c(newD1, d[i, 2]), c(newD1, newD2))
      }
    })
    newDF <- as.data.frame(do.call(rbind, new))
    return(newDF)
  }

结果。

> colSplitter(data2)
  UniProt.ID Drug.IDs
1     P45059  DB00303
2     P19113  DB00117
3     P19113  DB00114
4     P57809  DB00303
5     P21548  DB00117
6     P21548  DB00954
7     P48502  DB00303
8     P18456  DB00117
9     P18456  DB49785

希望有所帮助。

答案 1 :(得分:1)

我会将Drug.IDs分割为;unlist,然后cbind将每个Uniprot.ID所需的重复次数分割为未列出的向量:

d <- read.csv(text='UniProt.ID,Drug.IDs
P45059,DB00303
P19113,DB00114; DB00117', stringsAsFactors=F)


drugs.split <- strsplit(d$Drug.IDs, '; ')

with(d, cbind(rep(UniProt.ID, sapply(drugs.split, length)), 
              unlist(drugs.split)))


#      [,1]     [,2]     
# [1,] "P45059" "DB00303"
# [2,] "P19113" "DB00114"
# [3,] "P19113" "DB00117"

强制使用factor并根据需要添加dimnames

答案 2 :(得分:0)

有多少人有双/三/四... ID?您可以使用grep。

简单地获取数据的子集
ind = grep(' ', data$UniProt.Id)

从原始文件中删除这些文件,创建一个包含重复的Uni值的新data.frame,然后再创建rbind?