【问题标题】:efficiently merging tables on substrings, not perfect matches有效地合并子字符串上的表,而不是完美匹配
【发布时间】:2016-08-05 19:01:20
【问题描述】:

我想在 R 或 Python 中合并两个表,每个表都有数万行。但是,我将无法合并完美匹配。我正在寻找一个键是另一个键的子字符串的情况。匹配的子字符串可以包含多个单词。 我正在寻找比下面的蛮力代码更快的解决方案。

https://stackoverflow.com/users/170352/brandon-bertelsen 给出了一个很好的答案,基于我最初建议的玩具数据。但是,它只匹配单个单词的子字符串。 (我最初并没有明确提出这个要求。)

这是我将用于这种情况的代码。

library(SPARQL)
library(parallel)
library(Hmisc)
library(tidyr)
library(dplyr)

my.endpoint <- "http://sparql.hegroup.org/sparql/"

go.query <- 'select *
where { graph <http://purl.obolibrary.org/obo/merged/GO>
{ ?goid
<http://www.geneontology.org/formats/oboInOwl#hasOBONamespace>
"biological_process"^^<http://www.w3.org/2001/XMLSchema#string> .
?goid rdfs:label ?goterm}}'
go.result <- SPARQL(url = my.endpoint, query = go.query)
go.result.frame <- go.result[[1]]

anat.query <- 'select distinct ?anatterm ?anatid
where { graph <http://purl.obolibrary.org/obo/merged/UBERON>
{ ?anatid <http://www.geneontology.org/formats/oboInOwl#hasDbXref> ?xr .
?anatid rdfs:label ?anatterm}}'

anat.result <- SPARQL(url = my.endpoint, query = anat.query)
anat.result.frame <- anat.result[[1]]

# slow but recognizes multi-word substrings
loop.solution <-
  mclapply(
    X = sort(anat.result.frame$anatid),
    mc.cores = 7,
    FUN = function(one.anat.id) {
      one.anat.term <-
        anat.result.frame$anatterm[anat.result.frame$anatid == one.anat.id]
      temp <-
        grepl(pattern = paste0('\\b', one.anat.term, '\\b'),
              x = go.result.frame$goterm)
      temp <- go.result.frame[temp , ]
      if (nrow(temp) > 0) {
        temp$anatterm <- one.anat.term
        temp$anatid   <- one.anat.id
        return(temp)
      }
    }
  )

loop.solution <- do.call(rbind, loop.solution)

# from Brandon
# fast, but doesn't recognize multi-word matches
sep.gather.soln <-
  separate(go.result.frame,
           goterm,
           letters,
           sep = " ",
           remove = FALSE) %>%
  gather(goid, goterm) %>%
  na.omit() %>%
  setNames(c("goid", "goterm", "code", "anatterm")) %>%
  select(goid, goterm, anatterm) %>%
  left_join(anat.result.frame) %>%
  na.omit()

【问题讨论】:

  • set( term +' '+ cat for term in terms for cat in set([ dictionary .get(word,'') for word in term.split()]) if cat)跨度>
  • 谢谢。我无法确定此代码中的换行符和缩进的位置。
  • 这是一行代码
  • 请使用真实数据更新您的示例。我不打算安装所有这些软件包,所以只关注我需要解决您遇到的问题的最后一部分所需的数据。显示非常清晰的示例输入和输出。

标签: python r string optimization


【解决方案1】:

我正在使用您的原始帖子数据。
第一个拆分词
第二次检查字典中的关联项目
第三个结合在一起

terms =["cheese omelette","turkey sandwich","bean soup",]
dictionary ={'turkey': 'meat', 'cheese': 'dairy', 'sandwich': 'bread', 'beef': 'meat', 'omelette': 'eggs', 'bean': 'legume', 'carrot': 'vegetable', 'milk': 'dairy'}

res = set( term +' '+ cat for term in terms for cat in set([ dictionary .get(word,'') for word in term.split()]) if cat) 

for i in res:
    print i


output:
cheese omelette dairy
bean soup legume
turkey sandwich meat
turkey sandwich bread
cheese omelette eggs

【讨论】:

  • 感谢您发布作为答案。是的,当字典对的关键部分是一个单词时,这很好用。我最初对密钥可以是多个单词的要求不够清楚,所以我更新了这个问题。对不起移动的目标。我现在在生产中使用我的循环解决方案,但我仍然愿意接受使用多字键的建议。
【解决方案2】:
library(tidyr)
library(dplyr)

df1 <- data.frame(
  mealtime = c("breakfast","lunch","dinner","dinner"),
  dish = c(
    "cheese omelette",
    "turkey sandwich",
    "bean soup",
    "something very long like this")
)

df2 <- read.table(textConnection(
'ingredient  category
bean        legume
beef        meat
carrot      vegetable
cheese      dairy
milk        dairy
omelette    eggs
sandwich    bread
turkey      meat'), header = TRUE)

df1 <- separate(df1, dish, letters, sep = " ", remove = FALSE) %>% 
  gather(mealtime, dish) %>% 
  na.omit() %>% setNames(c("mealtime","dish","code","ingredient")) %>% 
  select(mealtime, dish, ingredient) %>% 
  left_join(df2) %>% na.omit()

df1

mealtime dish ingredient category 1 breakfast cheese omelette cheese dairy 2 lunch turkey sandwich turkey meat 3 dinner bean soup bean legume 5 breakfast cheese omelette omelette eggs 6 lunch turkey sandwich sandwich bread

【讨论】:

  • 谢谢,布兰登。抱歉,我的示例表不清楚。我的问题的症结在于连接列之间不会完美匹配,因此标准合并不起作用。
  • 不,不总是两个词。我试图在不同的生物医学本体之间进行匹配。例如,“抑制肾上皮发育”和“肾上皮”之间的匹配。或者介于“突发心脏病”和“心脏”之间。
  • 改变方法,融化所有可能性,丢弃缺失,合并,丢弃缺失。
  • 哇,看起来不错。我很快就会在“真实”数据上进行尝试。我将针对两个嵌套循环和一个 grepl 对其进行基准测试。
  • 当然,您可以通过将“into”字段限制为菜肴的最大字长来获得一些改进。现在我只是用返回 a:z 的字母 jimmy'd。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-08
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 2018-11-05
相关资源
最近更新 更多