【问题标题】:Multiple matching function in rr中的多重匹配函数
【发布时间】:2017-01-31 10:45:59
【问题描述】:

我正在尝试使用以下变量 School(唯一)将两个数据集与需要教师的课程进行匹配。有的老师有一种专长,有的有不止一种。我一直在尝试使用 match() 和 which( %in% ) 基本函数,但我无法让它搜索所有可能的教师匹配项。它总是在第一场比赛后停止。以下是一些示例数据:

class<-c("english","history","art","art","math","history","art")
school<-c("C.H.S.","B.H.S.","D.H.S.","A.H.S.","Z.H.S.","M.H.S.","L.H.S.")
specialty<-c("math","history","English","history","literature","art","English")
teacher<-c("Jill","Jill","Sam","Liz","Liz","Liz","Rob")
teacher.skills<-data.frame(teacher, specialty)
school.needs<-data.frame(school,class)
teacher.match<-data.frame(Jill,Sam,Rob,Liz)

最终结果如下所示:

Jill<-c("No","Yes","No","No","Yes","Yes","No")
Sam<-c("Yes","No","No","No","No","No","No")
Liz<-c("No","Yes","Yes","Yes","No","Yes","Yes")
Rob<-c("Yes","No","No","No","No","No","No")
match.result<-data.frame(school.needs, teacher.match)
match.result

我什至尝试过使用这样的小功能,但仍然无法正确设置最终格式。

source.1<-school.needs
source.2<-teacher.skills
dist.name<-adist(source.1$class, source.2$specialty, partial = FALSE, ignore.case = TRUE)
min.name<-apply(dist.name, 1, min)
school.teacher.match<-NULL  
for(i in 1:nrow(dist.name))
{
    skills.ref<-match(min.name[i], dist.name[i,])
    school.ref<-i
    school.teacher.match<-rbind(data.frame(skills.ref=skills.ref, school.ref=school.ref, Teacher=source.2[skills.ref,]$teacher, Class=source.1[school.ref,]$class, School=source.1[school.ref,]$school, adist=min.name[i]), school.teacher.match)
    school.teacher.match<-subset(school.teacher.match, school.teacher.match$adist==0)
}
school.teacher.match

任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: r function matching string-matching


    【解决方案1】:

    请注意,我必须修改您的输入数据以将每次匹配的 "English" 更改为 "english"。数据由:

    school.needs <- structure(list(school = structure(c(3L, 2L, 4L, 1L, 7L, 6L, 5L
    ), .Label = c("A.H.S.", "B.H.S.", "C.H.S.", "D.H.S.", "L.H.S.", 
    "M.H.S.", "Z.H.S."), class = "factor"), class = structure(c(2L, 
    3L, 1L, 1L, 4L, 3L, 1L), .Label = c("art", "english", "history", 
    "math"), class = "factor")), .Names = c("school", "class"), row.names = c(NA, 
    -7L), class = "data.frame")
    
    teacher.skills <- structure(list(teacher = structure(c(1L, 1L, 4L, 2L, 2L, 2L, 
    3L), .Label = c("Jill", "Liz", "Rob", "Sam"), class = "factor"), 
    specialty = structure(c(5L, 3L, 2L, 3L, 4L, 1L, 2L), .Label = c("art", 
    "english", "history", "literature", "math"), class = "factor")), .Names = c("teacher", 
    "specialty"), row.names = c(NA, -7L), class = "data.frame")
    

    使用来自reshape2(或data.table)的mergedcast

    library(reshape2)
    ## use merge to match needs to skills
    m <- merge(school.needs,teacher.skills,by.x="class",by.y="specialty")
    m$val <- "Yes"   ## add a column for the "Yes"
    ## go to wide format for the final result filling NA with "No"
    result <- dcast(m,school+class~teacher,value.var="val",fill="No")
    ##  school   class Jill Liz Rob Sam
    ##1 A.H.S.     art   No Yes  No  No
    ##2 B.H.S. history  Yes Yes  No  No
    ##3 C.H.S. english   No  No Yes Yes
    ##4 D.H.S.     art   No Yes  No  No
    ##5 L.H.S.     art   No Yes  No  No
    ##6 M.H.S. history  Yes Yes  No  No
    ##7 Z.H.S.    math  Yes  No  No  No
    

    【讨论】:

    • 非常感谢,很高兴看到不同的解决方案。
    【解决方案2】:

    我会这样做:

    (数据)

    schools <- data.frame(
      school = c("C.H.S.", "B.H.S.", "D.H.S.", "A.H.S.","Z.H.S.", "M.H.S.", "L.H.S."),
      class  = c("english", "history", "art", "art", "math", "history", "art"),
      stringsAsFactors = F)
    
    teachers <- data.frame(
      teacher   = c("Jill", "Jill", "Sam", "Liz", "Liz", "Liz", "Rob"),
      specialty = c("math", "history", "English", "history", "literature", "art", "English"),
      stringsAsFactors = F)
    

    (关键概念)

    # you can get the specialties of a given teacher like this:
    subset(teachers, teacher == 'Jill')$specialty
    # [1] "math"    "history"
    
    # you can get the set of unique teachers like this:
    unique(teachers$teacher)
    # [1] "Jill" "Sam"  "Liz"  "Rob" 
    

    (解决方案)

    # for each teacher, do any of their specialties match the class need of each school?
    matches <- 
      sapply(unique(teachers$teacher), function(this_t) {
        specs <- subset(teachers, teacher == this_t)$specialty
        schools$class %in% specs
        })
    
    # combine with school data.frame
    data.frame(schools, matches)
    
    #   school   class  Jill   Sam   Liz   Rob
    # 1 C.H.S. english FALSE FALSE FALSE FALSE
    # 2 B.H.S. history  TRUE FALSE  TRUE FALSE
    # 3 D.H.S.     art FALSE FALSE  TRUE FALSE
    # 4 A.H.S.     art FALSE FALSE  TRUE FALSE
    # 5 Z.H.S.    math  TRUE FALSE FALSE FALSE
    # 6 M.H.S. history  TRUE FALSE  TRUE FALSE
    # 7 L.H.S.     art FALSE FALSE  TRUE FALSE
    

    一些注意事项:

    1) 当您在代码中包含适当的间距时,它会更容易阅读(和思考)。此外,与其创建一堆向量然后组装成 data.frames,不如一步完成——它更短,它有助于显示向量如何相互关联,并且不会弄乱您的全局环境。

    2) 我将匹配值保留为 FALSE/TRUE,因为这是布尔数据,因此使用适当的数据类型是有意义的。但是,如果您真的想要 No/Yes,您可以使用这些标签将这些值更改为因子

    3) 结果与您的预期略有不同,因为'English' == 'english'FALSE。您可能想要清理您的起始数据。如果您知道大小写会混合并且您不区分大小写匹配,则可以在比较之前将所有值强制为小写:tolower(schools$class) %in% tolower(specs)

    【讨论】:

    • 这太棒了,感谢这里的提示和解决方案!
    • 我做了,但我太新了,无法在页面上注册
    猜你喜欢
    • 2022-08-13
    • 2012-10-30
    • 1970-01-01
    • 2021-12-11
    • 2017-03-28
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多