2013-04-23 24 views
3

我需要合并两个数据帧。第一个是这样的:合并具有可预测输入错误的数据帧

> df1 <- data.frame(Artist = c("Vincent van ", "Vincent van ", "Theo van Gogh", "Alexandre", "Alexandre"), Location = c("a","a","a","b","c"), time = c(1,2,1,1,1)) 
> df1 
     Artist Location time 
1 Vincent van   a 1 
2 Vincent van   a 2 
3 Theo van Gogh  a 1 
4  Alexandre  b 1 
5  Alexandre  c 1 

而第二个:

> df2 <- data.frame(Artist = c("Vincent van Gogh", "Theo van Gogh", "Alexandre Dumas", "Alexandre Dumas"), HomeNumber = c(123,234,456,789), Location = c("a","a","b","c")) 
> df2 
      Artist HomeNumber Location 
1 Vincent van Gogh  123  a 
2 Theo van Gogh  234  a 
3 Alexandre Dumas  456  b 
4 Alexandre Dumas  789  c 

而且我想这个数据帧:

> df3 <- data.frame(Artist = c("Vincent van ", "Vincent van ", "Theo van Gogh", "Alexandre", "Alexandre"), Location = c("a","a","a","b","c"), time = c(1,2,1,1,1), HomeNumber = c(123,123,234,456,789)) 
> df3 
     Artist Location time HomeNumber 
1 Vincent van   a 1  123 
2 Vincent van   a 2  123 
3 Theo van Gogh  a 1  234 
4  Alexandre  b 1  456 
5  Alexandre  c 1  789 
> 

合并将只西奥工作:

> df3 <- merge(df1, df2, by.x = "Artist", by.y = "Artist", all.x =TRUE) 
> df3 
     Artist Location.x time HomeNumber Location.y 
1  Alexandre   b 1   NA  <NA> 
2  Alexandre   c 1   NA  <NA> 
3 Theo van Gogh   a 1  234   a 
4 Vincent van   a 1   NA  <NA> 
5 Vincent van   a 2   NA  <NA> 

的原因是双重的: (a)文森特在df1中缺少他姓氏的一部分。 (b)亚历山大是亚历山大杜马高级和亚历山大杜马低级大三的名字。

我可以解决(a)与df1$Artist <- gsub("Vincent van $","Vincent van Gogh", df1$Artist),但我的数据其实非常大,并且在执行gsub之前我必须先知道文森特的全名。一个可能的解决方案将是在使用DF2 grep("Vincent van "...,构建一个功能是,如果所得到的矢量的长度是1我会使用gsub使用返回df2$Artistdf1。我不知道该怎么做。

(b)是对我来说有点棘手。一个解决方案,我能想到的(但不能代码)是使用if函数首先从一个位置选择亚历山大,再使用(一)gsub名称的解决方案。

我认为解决的(a)和(b)将返回我的期望df3。你们有没有想法我可以如何有效地合并这些数据框?谢谢!

编辑:请注意,Alexandre,其实是两个不同的单位。因此,合并两者时应该有相关的HomeNumber和Location。 Vincent是一个单一的单位,但有两个观察时间。

+0

你可以用'匹配()'函数,在那里你可以把'location'作为匹配的参数和列的其余部分显示尝试在一个新的数据框架 – Duck 2013-04-23 17:13:40

+0

函数'agrep'做模糊字符串匹配。您还可以采取一些像'tolower'这样的消除步骤,并删除标点符号来帮助......但最简单的答案是数据消除非常乏味! – Justin 2013-04-23 17:22:48

+0

@Duck:这可能有帮助,但我看不出它将如何解决问题。谢谢! @Justin:我知道!非常乏味。我已经使用了'tolower','chartr'和一些其他功能。 – Lucarno 2013-04-23 17:36:45

回答

2

你希望这个结果受到这样一个事实的破坏,你必须在每个数据帧中有两行,你要考虑使用相同的id,即Alexandre行。加入过程将是一个2×2的比赛:

df2$short <- substr(df2$Artist, 1,7) 
df1$short <- substr(df1$Artist, 1,7) 
(dfmer <- merge(df1, df2, by="short")) 
#----- 
    short  Artist.x Location.x time   Artist.y HomeNumber Location.y 
1 Alexand  Alexandre   b 1 Alexandre Dumas  456   b 
2 Alexand  Alexandre   b 1 Alexandre Dumas  789   c 
3 Alexand  Alexandre   c 1 Alexandre Dumas  456   b 
4 Alexand  Alexandre   c 1 Alexandre Dumas  789   c 
5 Theo va Theo van Gogh   a 1 Theo van Gogh  234   a 
6 Vincent Vincent van   a 1 Vincent van Gogh  123   a 
7 Vincent Vincent van   a 2 Vincent van Gogh  123   a 

您可以使用复制位置和时间,如果你想挑出来的第一个实例:

> dfmer[!duplicated(dfmer[, c("Location.x", "time")]), ] 
    short  Artist.x Location.x time   Artist.y HomeNumber Location.y 
1 Alexand  Alexandre   b 1 Alexandre Dumas  456   b 
3 Alexand  Alexandre   c 1 Alexandre Dumas  456   b 
5 Theo va Theo van Gogh   a 1 Theo van Gogh  234   a 
7 Vincent Vincent van   a 2 Vincent van Gogh  123   a 

针对关注(以前没有提出该位置需要添加一个链接变量:

> (dfmer <- merge(df1, df2, by=c("short", "Location"))) 
    short Location  Artist.x time   Artist.y HomeNumber 
1 Alexand  b  Alexandre 1 Alexandre Dumas  456 
2 Alexand  c  Alexandre 1 Alexandre Dumas  789 
3 Theo va  a Theo van Gogh 1 Theo van Gogh  234 
4 Vincent  a Vincent van  1 Vincent van Gogh  123 
5 Vincent  a Vincent van  2 Vincent van Gogh  123 
+0

谢谢@Dwin。但是,请注意,来自'Location''c'的'Alexandre'有错误的HomeNumber – Lucarno 2013-04-29 21:10:40

+0

如果HomeNumber与共享标识符相关联,因为我相信它是使用Location,那么您应该将标识符添加到'by'变量。 – 2013-04-29 22:43:55

+0

对不起,我没有说清楚。 – Lucarno 2013-04-30 13:05:07