基于两个列值合并数据集

时间:2014-03-11 20:46:21

标签: r merge dataframe

我到处寻找,我似乎无法找到解决这个小问题的可行办法。

我有两个大数据集,N = 875和N = 922。

df.1数据设置为875 obs和27 var df.2数据设置为922 obs 23 var

df.1包含FIRSTLAST列,这些列是个人的名字和姓氏,以及其他25个列。

df.2X1X2对应于个人的名字和姓氏,以及其他21个列。

我需要将df.1df.2合并,并丢弃任何不在两个帧中的观察结果。

所以我现在应该有一个少于875个观测值和48列的数据框。

有什么建议吗?

由于

2 个答案:

答案 0 :(得分:4)

考虑到df1和df2的变量名称完全相同,您可以尝试

merge(df1, df2, by = c('X1', 'X2'), all = F)

在您的情况下,您需要

merge(df.1, df.2, by.x = c('FIRST', 'LAST'), by.y = c('X1', 'X2'))

对于提供的数据集:

library(XML)
url1 <- "http://stats.nhlnumbers.com/player_stats/year/2010"
df1 <- readHTMLTable(url1)
names <- data.frame(do.call(rbind, strsplit(as.character(df1[[1]][ ,1]),
                                            split = ", ")))
df1 <- cbind(df1, names)
#head(df1)

url2 <- "http://stats.nhlnumbers.com/player_stats/year/2009"
df2 <- readHTMLTable(url2)
names2 <- data.frame(do.call(rbind, strsplit(as.character(df2[[1]][ ,1]),
                                             split = ", ")))
df2 <- cbind(df2, names2)
#head(df2)

df1_2 <- merge(df1, df2, by = c('X1', 'X2'), all = F)
head(subset(df1_2, select = c('X1', 'X2', 'skaters-data.Name.x',
                              'NULL.PTS/$MM.x', 'NULL.PTS/$MM.y')))
df1_2$Player <- paste(df1_2$X2, df1_2$X1)
url3 <- "http://hockey-reference.com/leagues/NHL_2010_skaters.html"
df3 <- readHTMLTable(url3)
df3 <- as.data.frame(df3)

df4 <- merge(df1_2, df3, by.x = 'Player', by.y = 'stats.Player', all = F)
names(df4) <- gsub("[[:punct:]]", "_", names(df4))
head(subset(df4, select = c(X2, X1, Player, NULL_PTS__MM_x,
                            NULL_PTS__MM_y, stats_Rk)))

     X2      X1        Player NULL_PTS__MM_x NULL_PTS__MM_y stats_Rk
1 Aaron Johnson Aaron Johnson         18.519         15.573      344
2 Aaron    Rome    Aaron Rome          7.619          6.698      662
3 Aaron   Voros   Aaron Voros          7.000         16.000      825
4 Aaron    Ward    Aaron Ward          5.200          4.000      834
5  Adam  Burish   Adam Burish          5.614         12.632       95
6  Adam   Foote    Adam Foote          3.000          2.333      228

也许可以画出来

df5 <- subset(df4, select = c(X2, X1, Player, NULL_PTS__MM_x,
                              NULL_PTS__MM_y, stats_Rk))[1:10, ]

library(ggplot2)
ggplot(aes(x = as.numeric(NULL_PTS__MM_x), y = as.numeric(stats_Rk),
       colour = Player), data = df5) +
  geom_point()

plot it

答案 1 :(得分:3)

base::merge外,还有一种方法是使用SQL

您可以将Rsqldf一起使用(但将您的数据重命名为df1df2而不使用点.

library(sqldf )
sqldf("SELECT *
      FROM df1, df2
      WHERE df1.FIRST==df2.X1
      and df1.LAST == df2.X2")

另一种选择是data.table,如果你有大数据集,你应该考虑这个:

library(data.table)
dt1 <- data.table(df1, key=c("FIRST", "LAST")) #set keys
dt2 <- data.table(df2, key=c("X1", "X2")) #set keys
dt1[dt2] #join

data.table版本&gt; = 1.9开始,有一个函数setDT可将data.frame(以及list)转换为{{1} } 引用。这样可以提高速度和内存效率(特别是在数据为5GB且内存为8GB的情况下)。所以,可以这样做:

data.table