在R中,我想提取完成我设计的两个版本测试的人员,然后分两个阶段进行管理(我向参与者询问他们的名字和姓氏)。
问题在于1.人们在使用资本方面并不一致; 2.有些人可能会与其他人分享名字或姓氏。因此,1。我需要一个不区分大小写的搜索; 2.我想提取一个新的数据框,列出第一个版本的名字和姓氏,以及第二个版本的名字和姓氏,以便验证匹配(也因为某人可能会使用&#34 ; Tom"在一个实例中," Thomas"在另一个实例中:
df1 <- data.frame(firstName = c("John", "Josef", "Tom", "Huckleberry", "Johann"),
lastName = c("Doe", "K", "Sawyer", "Finn", "Bach"))
df2 <- data.frame(firstName = c("John", "josef", "Thomas", "Huck", "Pap", "Johann Sebastian", "Johann"),
lastName = c("Doe", "K", "Sawyer", "Finn", "Finn", "Bach", "Pachelbel"))
上述名称都应该与我匹配以验证:
repeatDF <- data.frame(firstName.1 = c("John", "Josef", "Tom", "Huckleberry", "Huckleberry", "Johann", "Johann"),
lastName.1 = c("Doe", "K", "Sawyer", "Finn", "Finn", "Bach", "Bach"),
firstName.2 = c("John", "josef", "Thomas", "Huck", "Pap", "Johann Sebastian", "Johann"),
lastName.2 = c("Doe", "K", "Sawyer", "Finn", "Finn", "Bach", "Pachelbel"))
然后我(可能手动?)批准所有人,但约翰·帕切尔贝尔&#34;并且&#34; Pap Finn&#34;,因为他们可能与名字匹配,但与他们匹配的人不是同一个人。
到目前为止,我已尝试merge
(另请参阅match two data.frames based on multiple columns)和%in%
,但这两种方法都区分大小写,并且错过了某些匹配项。我以某种方式无法使用apply
使用grep
函数(必须承认:这些函数不是很流畅),但也不知道如何考虑使用grep
的姓氏和姓氏?我是在寻找正确的方向,还是应该使用完全不同的功能?
非常感谢任何帮助!
PS。似乎有很多很多类似的问题,但要么是针对不同的程序,要么是不需要我的两个考虑因素 - 如果确实已经有了我的问题的答案,请道歉!
答案 0 :(得分:1)
这似乎基于OP的评论和新数据集。我稍微更改了df2
,因此两个数据框中的名称顺序不同。
df1 <- data.frame(firstName = c("John", "Josef", "Tom", "Huckleberry", "Johann"),
lastName = c("Doe", "K", "Sawyer", "Finn", "Bach"))
df2 <- data.frame(firstName = c("John", "josef", "Huck", "Pap", "Johann Sebastian", "Johann", "Thomas"),
lastName = c("Doe", "K", "Finn", "Finn", "Bach", "Pachelbel", "Sawyer"))
get.match <- function(A,B) {
A <- as.list(tolower(A)); B <- as.list(tolower(B))
match.last <- grepl(A$lastName,B$lastName)|grepl(B$lastName,A$lastName)
match.first <- grepl(A$firstName,B$firstName)|grepl(B$firstName,A$firstName)
match.first | match.last
}
indx <- apply(df2,1,function(row) apply(df1,1,get.match,row))
indx
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] TRUE FALSE FALSE FALSE FALSE FALSE FALSE
# [2,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE
# [3,] FALSE FALSE FALSE FALSE FALSE FALSE TRUE
# [4,] FALSE FALSE TRUE TRUE FALSE FALSE FALSE
# [5,] FALSE FALSE FALSE FALSE TRUE TRUE FALSE
m.1 <- df1[rep(1:nrow(df1),apply(indx,1,sum)),]
result <- cbind(m.1,do.call(rbind,apply(indx,1,function(i)df2[i,])))
result
# firstName lastName firstName lastName
# 1 John Doe John Doe
# 2 Josef K josef K
# 3 Tom Sawyer Thomas Sawyer
# 4 Huckleberry Finn Huck Finn
# 4.1 Huckleberry Finn Pap Finn
# 5 Johann Bach Johann Sebastian Bach
# 5.1 Johann Bach Johann Pachelbel
因此,这使用get.match(...)
中实现的算法,该算法将df1
行与df2
行进行比较,如果任一行中的第一个名称存在,则返回TRUE
在另一行或的第一个名称中,任一行中的姓氏都出现在另一行的姓氏中。这一行:
indx <- apply(df2,1,function(row) apply(df1,1,get.match,row))
然后创建一个indx
矩阵,其中行代表df1
中的行,列代表df2
的行,元素为TRUE
如果df1
和df2
的相应行匹配。这样就可以在df1
或df2
中进行多次匹配。最后,我们将此indx
矩阵转换为您想要使用的result
:
m.1 <- df1[rep(1:nrow(df1),apply(indx,1,sum)),]
result <- cbind(m.1,do.call(rbind,apply(indx,1,function(i)df2[i,])))
此代码提取在df1
中匹配的df2
的所有行,然后将其绑定到df2
的相应行。