基于第二个变量的匹配,从参考数据帧更新数据帧中的值

时间:2016-02-17 14:40:45

标签: r

我在R中有两个数据框,看起来像这样。

> df
    Var1 Freq
1   0.01    1
2      1   27
3    100   27
4   1000  488
5   2000    4
6   5000    7
7  50000    7
8 100000    1


> return_matrix
         Var1 Freq
1     0.00001    0
2        0.01    0
3           1    0
4           8    0
5         100    0
6         200    0
7         500    0
8        1000    0
9        2000    0
10       5000    0
11      10000    0
12      50000    0
13     100000    0
14     200000    0
15     500000    0
16    1000000    0
17   10000000    0
18  100000000    0
19 1000000000    0

我想像上面数据框的Vlookup那样做,以便输出如下所示:

  > combined
             Var1 Freq
    1     0.00001    0
    2        0.01    1
    3           1   27
    4           8    0
    5         100   27
    6         200    0
    7         500    0
    8        1000  488
    9        2000    4
    10       5000    7
    11      10000    0
    12      50000    7
    13     100000    1
    14     200000    0
    15     500000    0
    16    1000000    0
    17   10000000    0
    18  100000000    0

我尝试使用下面提到的R代码在R中执行合并。但是我没有像上面那样得到预期的结果。你能帮帮我吗?

> combined_matrix <- merge(return_matrix, df, by = "Var1" )
> combined_matrix
    Var1 Freq.x Freq.y
1   0.01      0      1
2      1      0     27
3    100      0     27
4   1000      0    488
5 100000      0      1
6   2000      0      4
7   5000      0      7
8  50000      0      7

3 个答案:

答案 0 :(得分:2)

这里没有必要合并任何东西。

id <- match(return_matrix$Var1, df$Var1, nomatch = 0L)
return_matrix$Freq[id != 0] <- df$Freq[id]

诀窍。

此代码将通过多种方式优于任何mergeplyr解决方案。在我的机器上进行以下模拟时,它比ddply快约100倍,比merge快约10倍:

library(plyr)
library(rbenchmark)
df <- data.frame(
  Var1 = c(0.01, 1, 100, 1000, 2000, 5000, 50000,100000),
  Freq = c(1,27,27,488,4,7,7,1)
)

return_matrix <- data.frame(
  Var1 = c(0.00001,0.01,1,8,100,200,500,1000,2000,5000,
           10000,50000,100000,200000,500000,1e6,1e7,1e8),
  Freq = 0
)



codeJM <- function(df, return_matrix){
  id <- match(return_matrix$Var1, df$Var1, nomatch = 0L)
  return_matrix$Freq[id != 0] <- df$Var1[id]
  return_matrix
}

codemerge <- function(df, return_matrix){
  combined_matrix <- merge(return_matrix, df, by = "Var1" , all = TRUE)
  combined_matrix$Freq <- combined_matrix$Freq.x+combined_matrix$Freq.y
  combined_matrix$Freq.x <- combined_matrix$Freq.y <- NULL
  combined_matrix
}

codeddply <- function(df, return_matrix){
  full <- rbind(df,return_matrix)
  combined <- ddply(full ,.(Var1),function(x) 
                      data.frame(Var1=x$Var1[1],Freq=sum(x$Freq)))
  combined
}

benchmark(
  codemerge(df, return_matrix),
  codeJM(df, return_matrix),
  codeddply(df, return_matrix),
  replications = 1000
)

给出:

                          test replications elapsed relative user.self 
3 codeddply(df, return_matrix)         1000    5.38    107.6      5.37        
2    codeJM(df, return_matrix)         1000    0.05      1.0      0.05        
1 codemerge(df, return_matrix)         1000    0.51     10.2      0.52

答案 1 :(得分:1)

您可以使用Joris建议的匹配函数,也可以使用plyr包中的ddply函数:

library(plyr)
full <- rbind(df,return_matrix)
combined <- ddply(full ,.(Var1),function(x) data.frame(Var1=x$Var1[1],Freq=sum(x$Freq)))

这将汇总Freq中的值,即使它们在return_matrix

中不为0

答案 2 :(得分:1)

您仍然可以通过选择merge来使用all.x = TRUE,这会保留所有行:

c<-merge(return_matrix, df, by = "Var1", all.x = TRUE)

这将创建第二个freq列,但您可以相当轻松地清理它

c<-c[, -2]
c[,2][which(is.na(c[,2]))]<- 0