2012-07-30 101 views
9

我有一个氨基酸位点的数据框,并且想要为这些位点的每个成对组合创建一个新的数据框。将R中数据框中的每对列粘贴在一起?

的原始数据将是这个样子:

df<-cbind(letters[1:5], letters[6:10], letters[11:15]) 
df 
[,1] [,2] [,3] 
[1,] "a" "f" "k" 
[2,] "b" "g" "l" 
[3,] "c" "h" "m" 
[4,] "d" "i" "n" 
[5,] "e" "j" "o" 

什么,我想是这样的:

newdf<-cbind(paste(df[,1],df[,2],sep=""),paste(df[,1],df[,3],sep=""),(paste(df[,2],df[,3],sep=""))) 
newdf 
    [,1] [,2] [,3] 
[1,] "af" "ak" "fk" 
[2,] "bg" "bl" "gl" 
[3,] "ch" "cm" "hm" 
[4,] "di" "dn" "in" 
[5,] "ej" "eo" "jo" 

的实际数据可能有数百个行和/或列的,所以很明显我需要一个较少的手动方式来做到这一点。任何帮助非常感谢,我只是一个谦虚的生物学家,我在这方面的技能是相当有限的。

+0

您是否希望只有与您的数据框相同的订单对?也就是说,为什么你的第一排不是“fa”或“ka”? – 2012-07-30 23:54:56

+0

谢谢,在身份方面,顺序并不重要,即“fa”=“af”,但是,对应与数据框的顺序相同,如示例 – 2012-07-30 23:58:53

回答

12

combn()apply()的组合将让你所有的无序两两连击:

df <- cbind(letters[1:5], letters[6:10], letters[11:15]) 

apply(X = combn(seq_len(ncol(df)), 2), 
     MAR = 2, 
     FUN = function(jj) { 
      apply(df[, jj], 1, paste, collapse="") 
     }  
) 
#  [,1] [,2] [,3] 
# [1,] "af" "ak" "fk" 
# [2,] "bg" "bl" "gl" 
# [3,] "ch" "cm" "hm" 
# [4,] "di" "dn" "in" 
# [5,] "ej" "eo" "jo" 

(如果有什么在上面是怎么回事不是立即清楚的,你可能希望有一个快速浏览一下对象通过combn(seq_len(ncol(df)), 2)返回。它的列枚举1和n,其中n是在数据帧的列数之间的所有无序两两连击整数)。

+0

+1刚刚拍完我来吧!删除了我的矿井 – 2012-07-31 00:09:22

+0

非常感谢 - 这正是我所需要的。为什么五个小时前我没有发布这个问题?你们都很棒。 – 2012-07-31 01:28:02

9

可以使用FUN参数combn的列从每个组合粘贴在一起:

combn(ncol(df),2,FUN=function(i) apply(df[,i],1,paste0,collapse="")) 
+1

+1甜美,甜美地模糊起动! – 2012-07-31 00:38:26

+0

@ JoshO'Brien:什么被混淆了呢? 'FUN'arg到'combn'可能看起来有点奇怪,但如果有很多组合,因为您不必将所有这些组合存储在中间对象中,它真的很方便。 – 2012-07-31 00:42:58

+1

@otherJosh - 混淆可能是错误的词。 '紧凑'会更好。作为一名以前的“谦逊的生物学家”,我只是在意如何解析这个问题(以及我对这个问题的答案)可能会给OP。 (只是要清楚,我仍然是一名生物学家---不再是一个卑微的人......) – 2012-07-31 00:49:14

2

Josh和约书亚的答案是更好,但我想我给我的方法:

library(qdap) 

ind <- unique(t(apply(expand.grid(1:3, 1:3), 1, sort))) 
ind <- ind[ind[, 1] != ind[, 2], ] 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 

这需要使用paste2功能下载qdap varsion 1.1.0

虽然从他们的答案中窃取,但这会更具可读性:

ind <- t(combn(seq_len(ncol(df)), 2)) 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 
-1

请记住,你会得到你的新data.frame列的很多,因为你说你有几百列在原data.frame:如果原始数据包含ñ列,那么新一个将包含n(n-1)/ 2列 - 这是按比例缩放的。

+3

这不是一个答案;你应该添加这个作为对问题的评论。 – 2012-07-31 10:11:46

+0

我只是试图将其更改为评论。然而,我有什么小代表,似乎我还不能评论问题。对于其他人来说,将其转化为评论意见还是有道理的,否则这会对垃圾邮件造成影响? – 2012-10-02 06:29:04