2016-08-19 68 views
0

我有两个数据帧,如何在R中的两个列数据框之间插入一个具有匹配条件的列?

DF1

Identifier GSE1028888 GSE1034555 
    100002   0.1   0.2 
    100003   0.3   0.4 
    ......   .....  ..... 
    100007   0.9   1.1 

DF2

  V3   V2 
    100002   XLX12   
    100003   ABorF   
    ......   .....  
    110000   GEF22 

现在我想插入V2信息到DF1,如

DF3

Identifier  New_V2 GSE1028888 GSE1034555 
    100002   XLX12   0.1   0.2 
    100003   ABorF   0.3   0.4 
    100004   NA   0.6   0.7 
    ......   .....  ..... 
    100007   ccL34   0.9   1.1   

df2的V3和df1的标识符具有不同的长度。 我尝试dplyr left_join,但该列附在最后。

这是代码来创建类似的数据帧

df1 <- data.frame("Identifier" = sample(100001:100010, 6, replace = F), 
       y = sample(rnorm(10), 6, replace = T), 
       z = sample(rnorm(10), 6, replace = T)) 
df2 <- data.frame(V1 = c(100001:100010), 
       V2 = sample(state.name, 10, replace = T)) 

这个时候,当我尝试dplyr left_join,

left_join(df1, df2, by =c("Identifier"="V3")) 

显示出错误消息

Error: cannot join on columns 'V3' x 'Identifier': index out of bounds 

任何人有任何理念?

+0

您的问题不包含[reproducible example](http://stackoverflow.com/q/5963269/4303162)。因此很难理解你的问题并给你一个合适的答案。请提供您的数据(例如使用'dput()')或使用R中的示例数据集之一。另外,添加将您的问题重现到您的文章所需的最小代码。 – Stibu

回答

1

使用你提供的数据:

df1 <- data.frame("Identifier" = sample(100001:100010, 6, replace = F), 
       y = sample(rnorm(10), 6, replace = T), 
       z = sample(rnorm(10), 6, replace = T)) 
df2 <- data.frame(V1 = c(100001:100010), 
       V2 = sample(state.name, 10, replace = T)) 

merge(df2, df1, by.x="V1",by.y="Identifier", all.x=TRUE) 
     V1   V2   y   z 
1 100001  Wisconsin -1.9468637 0.4509951 
2 100002  Nebraska 2.5155819 0.4509951 
3 100003   Ohio   NA   NA 
4 100004 Massachusetts   NA   NA 
5 100005  Montana -1.9468637 -2.1825878 
6 100006  Illinois -0.1591367 0.3445637 
7 100007 New Mexico -0.5696300 0.4509951 
8 100008 New Jersey   NA   NA 
9 100009  Tennessee   NA   NA 
10 100010 Washington -1.9468637 -0.5402241 

而且您可以切换曾经方式你喜欢哪个顺序,但上面的输出是你要求的-no需要重新排序,但如果想:

merge(df2, df1, by.x="V1",by.y="Identifier", all.x=TRUE)[c(2,3,4,1)] 
       V2   y   z  V1 
1  Wisconsin -1.9468637 0.4509951 100001 
2  Nebraska 2.5155819 0.4509951 100002 
3   Ohio   NA   NA 100003 
4 Massachusetts   NA   NA 100004 
5  Montana -1.9468637 -2.1825878 100005 
6  Illinois -0.1591367 0.3445637 100006 
7  New Mexico -0.5696300 0.4509951 100007 
8  New Jersey   NA   NA 100008 
9  Tennessee   NA   NA 100009 
10 Washington -1.9468637 -0.5402241 100010 

按照下面的OP的发表的评论,这里是一个标识符,在不存在DF2存在DF1的例子

df1 <- data.frame("Identifier" = sample(100001:100012, 6, replace = F), 
       y = sample(rnorm(10), 6, replace = T), 
       z = sample(rnorm(10), 6, replace = T)) 

df1 
    Identifier   y   z 
1  100011 -1.60532712 1.365836073 
2  100007 -1.28821500 0.005925986 
3  100004 -0.03444609 0.780708952 
4  100006 0.32190045 0.780708952 
5  100009 -1.60532712 -1.471916384 
6  100005 -0.76985033 0.191956916 

df2 <- data.frame(V1 = c(100001:100010), 
       V2 = sample(state.name, 10, replace = T)) 
df2 
     V1   V2 
1 100001 Pennsylvania 
2 100002 West Virginia 
3 100003   Utah 
4 100004  Alaska 
5 100005   Ohio 
6 100006 Mississippi 
7 100007 New Hampshire 
8 100008 New Jersey 
9 100009   Ohio 
10 100010  Georgia 

merge(df2, df1, by.x="V1",by.y="Identifier", all.x=TRUE, all.y=TRUE) 
     V1   V2   y   z 
1 100001 Pennsylvania   NA   NA 
2 100002 West Virginia   NA   NA 
3 100003   Utah   NA   NA 
4 100004  Alaska -0.03444609 0.780708952 
5 100005   Ohio -0.76985033 0.191956916 
6 100006 Mississippi 0.32190045 0.780708952 
7 100007 New Hampshire -1.28821500 0.005925986 
8 100008 New Jersey   NA   NA 
9 100009   Ohio -1.60532712 -1.471916384 
10 100010  Georgia   NA   NA 
11 100011   <NA> -1.60532712 1.365836073 
+0

感谢CM,但df1中的标识符可能有一些不是V1的变量,尽管在我创建的数据集中没有看到这种情况。所以,你匹配的方式可能会消除那些在V1中找不到的变量,我不希望发生这种情况。但感谢您的想法,以切换数据的顺序。 – pill45

+0

太棒了!如果我想删除列Y或列Z中的NA而不是V2,我可以使用merge()还是必须单独执行它? – pill45

+0

@pill你可以单独做为'dplyr :: filter(data,y!=“NA”)''。如果你喜欢这个答案,考虑接受它,以便你的帖子被标记为已解决。 –

4

一个解决方案是合并和重新排序(不幸的是不是一个单一功能的答案)。

设置

df1 = data.frame(i=c(1,2,3), GSE111=c(4,5,6), GSE222=c(7,8,9)) 
df2 = data.frame(i=c(1,3,4), v2=c(10,11,12)) 

这将产生:

> df1 
    i GSE111 GSE222 
1 1  4  7 
2 2  5  8 
3 3  6  9 
4 4  7  10 

> df2 
    i v2 
1 1 10 
2 3 11 
3 4 12 

合并:

我用内置的合并功能,而不是plyr。

df3 = merge(x=df1, y=df2, by="i", all.x=TRUE) 

这将产生:

i GSE111 GSE222 v2 
1 1  4  7 10 
2 2  5  8 NA 
3 3  6  9 11 

重新排序:

现在你可以从字面上键入列名重新排序:

df4 = df3[,c("i", "v2", "GSE111", "GSE222")] 

这将产生

i v2 GSE111 GSE222 
1 1 10  4  7 
2 2 NA  5  8 
3 3 11  6  9 

这实质上就是你想要的产品。



快捷键:

或者,如果你是懒惰和我一样,我可以生成这样DF1和DF2之间唯一的列名:

unique(c(colnames(df2), colnames(df1))) 

这产生了:

[1] "i"  "v2"  "GSE111" "GSE222" 

所以,你可以键入类似:

df3[,unique(c(colnames(df2), colnames(df1)))] 
+0

谢谢。一个问题,将unique()更改i后的列顺序。假设我想要GSE111,GSE333,GSE222的订单,在使用unique()后它会变成GSE111,GSE222,GSE333吗?对于重新排序,如果df1有很多列,超过100个,有没有更简单的方法来解决这个问题? – pill45

+0

它没有记录,但独特()似乎没有重新排序我的经验中的元素。它只是过滤掉后续的重复条目。例如,'unique(c('a','c','a','b'))'将输出“a”“c”“b”'。虽然我不认为它会弄乱你的基因表达谱序,但我总是检查我的工作。 – Shin

+0

@shin这就是为什么你的“捷径”是不必要的。 “唯一”与订购变量无关。你得到你想要的结果,因为表达式中的第一个数据帧是df2。 ''df3 [,unique(c(colnames(df2),colnames(df1)))]''但是你甚至不需要这样做,就像你在我的文章中看到的那样,如果你在原文中切换df1和df2合并,那么所有其他的'reorder','unique'和索引命令是完全不必要的,甚至在处理复杂的数据帧时可能会导致错误。 –

相关问题