我在R中有两个不同的数据帧,我试图合并在一起。一个是一组名称,另一个是一组名称,每个人都有相应的信息。
所以说我想采用第一个数据帧:
Name
1. Blow, Joe
2. Smith, John
3. Jones, Tom
etc....
并将其合并到这个:
DonorName CandidateName DonationAmount CandidateParty
1 blow joe Bush, George W 3,000 Republican
2 guy some Obama, Barack 5,000 Democrat
3 smith john Reid, Harry 4,000 Democrat
这样我就有了一个新列表,其中只包含第一个列表中包含第二个列表信息的人员。是两个"名称"以相同的方式格式化的值,我可以使用merge(),但有没有办法以某种方式使用agrep()或pmatch()来做到这一点?
此外,我正在使用的第二个数据帧中有大约2500万行和6列,那么使for循环成为最快的方法吗?
示例数据的可重现版本:
first <- data.frame(Name=c("Blow, Joe","Smith, John","Jones, Tom"),
stringsAsFactors=FALSE)
second <- read.csv(text="
DonorName|CandidateName|DonationAmount|CandidateParty
blow joe|Bush, George W|3,000|Republican
guy some|Obama, Barack|5,000|Democrat
smith john|Reid, Harry|4,000|Democrat",header=TRUE,sep="|",
stringsAsFactors=FALSE)
答案 0 :(得分:3)
first$DonorName <- gsub(", "," ",tolower(first$Name),fixed=TRUE)
require(dplyr)
result <- inner_join(first,second,by="DonorName")
如果数据是您提供的,将为您提供所需的信息。
result
Name DonorName CandidateName DonationAmount CandidateParty
1 Blow, Joe blow joe Bush, George W 3,000 Republican
2 Smith, John smith john Reid, Harry 4,000 Democrat
上述dplyr
方法:
f_dplyr <- function(left,right){
left$DonorName <- gsub(", "," ",tolower(left$Name),fixed=TRUE)
inner_join(left,right,by="DonorName")
}
data.table
方法,先设置密钥。
f_dt <- function(left,right){
left[,DonorName := gsub(", "," ",tolower(Name),fixed=TRUE)]
setkey(left,DonorName)
left[right,nomatch=0L]
}
data.table
方法,设置两个键。
f_dt2 <- function(left,right){
left[,DonorName := gsub(", "," ",tolower(Name),fixed=TRUE)]
setkey(left,DonorName)
setkey(right,DonorName)
left[right,nomatch=0L]
}
base
方法依赖sapply
:
f_base <- function(){
second[second$DonorName %in%
sapply(tolower(first[[1]]), gsub, pattern = ",", replacement = "", fixed = TRUE), ]
}
让我们在1M obs中使第二个df更加真实,以便进行公平的比较:
second <- cbind(second[rep(1:3,1000000),],data.frame(varn= 1:1000000))
left <- as.data.table(first)
right <- as.data.table(second)
library(microbenchmark)
microbenchmark(
f_base(),
f_dplyr(first,second),
f_dt(left,right),
f_dt2(left,right),
times=20)
我们得到:
Unit: milliseconds
expr min lq median uq max neval
f_base() 2880.6152 3031.0345 3097.3776 3185.7903 3904.4649 20
f_dplyr(first, second) 292.8271 362.7379 454.6864 533.9147 774.1897 20
f_dt(left, right) 489.6288 531.4152 605.4148 788.9724 1340.0016 20
f_dt2(left, right) 472.3126 515.4398 552.8019 659.7249 901.8133 20
在我的计算机上,使用此?人工示例,我们比base
方法获得 2.5秒。根据我的经验,sapply
简化并且不能很好地扩展...当您增加first
和second
中的唯一群组数量时,这种差距可能会变大。
如果您能更有效地使用,请随时修改。我不会假装知道,但我总是试着学习一些东西。
答案 1 :(得分:0)
没有dplyr
:
second[second$DonorName %in%
sapply(tolower(first[[1]]), gsub, pattern = ",", replacement = "", fixed = TRUE), ]
结果:
# DonorName CandidateName DonationAmount CandidateParty
# 1 blow joe Bush, George W 3,000 Republican
# 3 smith john Reid, Harry 4,000 Democrat