【问题标题】:Comparing strings and extracting differences at the phrase-level in R在 R 中比较字符串并在短语级别提取差异
【发布时间】:2020-09-22 16:46:58
【问题描述】:

我正在尝试比较数据框中包含字符串的两列并提取差异。但是,我看到的所有解决方案都在字符级别提取差异,并且我希望提取整个单词/短语。我有一个这样的数据框:

TECH_ID YRTR    pre_drop_courses                post_drop_courses               unchanged
71795   20213   BUSN 2100,BUSN 2400,ACCT 2254   BUSN 1102,BUSN 1102,BUSN 1102   FALSE
71795   20183   BUSN 1102,BUSN 1102,BUSN 1102   BUSN 2100,BUSN 2400,ACCT 2254   FALSE
73677   20183   BIOL 2041,BIOL 2041,BIOL 2041   BIOL 2042,BIOL 2042,BIOL 2042   FALSE
73677   20193   BIOL 2042,BIOL 2042,BIOL 2042   BIOL 2041,BIOL 2041,BIOL 2041   FALSE

对于 pre_drop 和 post_drop 列之间存在差异的行,我想提取不同的整个课程代码。理想情况下,我会有一个专栏来说明哪些课程被删除了,哪些课程被添加了。例如,在第一行中,BUSN 2100、BUSN 2400 和 ACCT 2254 都将出现在“已删除”列中,而 BUSN 1102 将出现在“已添加”列中。同样,在第三行中,我们会看到 BIOL 2041 被删除,而 BIOL 2042 被添加。

已编辑以显示 dput(head(mydata, 3)) 的结果

structure(list(TECH_ID = c("00000108", "00000108", "00000270"
), YRTR = c("20173", "20173", "20183"), pre_drop_courses = c("MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281", 
"MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281", 
"ACCT 1853,ACCT 1853,ACCT 1853"), post_drop_courses = c("MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281", 
"MUSC 1116,MUSC 1116,MUSC 1116", "ACCT 1853,ACCT 1853,ACCT 1853"
), unchanged = c(TRUE, FALSE, TRUE)), row.names = c(NA, 3L), class = "data.frame")

【问题讨论】:

  • 只是为了确保您的数据是我认为的数据,请您编辑您的问题以显示dput(head(mydata, 3)) 的结果,谢谢。
  • @ChuckP 已编辑!
  • 谢谢,但为什么在第 1 行中,学生的同一课程列出了 3 次?
  • @ChuckP 这可能是因为学生多次添加/删除课程,并且在较早的数据框中他们有多个时间戳。因此,如果学生添加课程、删除课程并添加差异部分,它将显示为 3 个单独的实例。我计划在以后的步骤中减少重复的课程名称。
  • 哈哈,这就是为什么我们喜欢我们的“学生信息系统”

标签: r string dataframe


【解决方案1】:

请允许我处理使课程列表独一无二的过程,因为它使解决方案更简洁。

加载stringr 以去除任何不必要的空格,然后将课程字符串拆分为课程向量...

library(stringr)
df$pre <- stringr::str_split(stringr::str_squish(df$pre_drop_courses), ",")
df$post <- stringr::str_split(stringr::str_squish(df$post_drop_courses), ",")

使用Map获取prepost的课程唯一值

df$pre <- Map(unique, df$pre)
df$post <- Map(unique, df$post)

使用Map 查找集合差异。一个方向是添加,另一个是下降

df$dropped <- Map(setdiff, df$pre, df$post)
df$added <- Map(setdiff, df$post, df$pre)

df
#>    TECH_ID  YRTR               pre_drop_courses             post_drop_courses
#> 1 00000108 20173  BUSN 2100,BUSN 2400,ACCT 2254 BUSN 1102,BUSN 1102,BUSN 1102
#> 2 00000108 20173 BUSN 1102,BUSN 1102,BUSN 1102  BUSN 2100,BUSN 2400,ACCT 2254
#> 3 00000270 20183  BIOL 2041,BIOL 2041,BIOL 2041 BIOL 2042,BIOL 2042,BIOL 2042
#>   unchanged                             pre                            post
#> 1      TRUE BUSN 2100, BUSN 2400, ACCT 2254                       BUSN 1102
#> 2     FALSE                       BUSN 1102 BUSN 2100, BUSN 2400, ACCT 2254
#> 3      TRUE                       BIOL 2041                       BIOL 2042
#>                           dropped                           added
#> 1 BUSN 2100, BUSN 2400, ACCT 2254                       BUSN 1102
#> 2                       BUSN 1102 BUSN 2100, BUSN 2400, ACCT 2254
#> 3                       BIOL 2041                       BIOL 2042

您的原始样本数据

df <- 
   structure(list(TECH_ID = c("00000108", "00000108", "00000270"), 
   YRTR = c("20173", "20173", "20183"), 
   pre_drop_courses = c("BUSN 2100,BUSN 2400,ACCT 2254", 
                        "BUSN 1102,BUSN 1102,BUSN 1102 ",
                        "BIOL 2041,BIOL 2041,BIOL 2041"), 
   post_drop_courses = c("BUSN 1102,BUSN 1102,BUSN 1102", 
                         "BUSN 2100,BUSN 2400,ACCT 2254", 
                         "BIOL 2042,BIOL 2042,BIOL 2042"
                                                             ), 
   unchanged = c(TRUE, FALSE, TRUE)), row.names = c(NA, 3L), class = "data.frame")

【讨论】:

  • 成功了!但是,我有一些添加/删除的列具有诸如“MUSC 1116”之类的值和一些具有 c(“MUSC 1116”) 的值 - 有没有办法将这些都转换为匹配?
  • 我可以请我看看产生这个奇数值的行之一的数据吗?
  • > dput(head(all_courses2, 1)) 结构(list(TECH_ID = "00000108", YRTR = "20173", pre_drop_courses = "MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281,MUSC 2231,MUSC 2281", post_drop_courses = "MUSC 1116,MUSC 1116,MUSC 1116", 不变 = FALSE, 添加 = list("MUSC 1116"), 删除 = list(c("MUSC 2231", "MUSC 2281")) , pre = list(c("MUSC 2231", "MUSC 2281")), post = list("MUSC 1116")), row.names = 1L, class= "data.frame")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多