【问题标题】:R: parse JSON/XML exported compound properties from PubchemR:解析从 Pubchem 导出的 JSON/XML 复合属性
【发布时间】:2015-09-17 15:33:33
【问题描述】:

我想使用 JSON(或 XML)导出工具解析 R 中 Pubchem 中给定化合物的所有化学性质。

示例:ALPHA-IONONE,pubchem 化合物 ID 5282108

https://pubchem.ncbi.nlm.nih.gov/compound/5282108

library("rjson")
data <- rjson::fromJSON(file="https://pubchem.ncbi.nlm.nih.gov/rest/pug_view/data/compound/5282108/JSON/?response_type=display")

library("RJSONIO")
data <- RJSONIO::fromJSON("https://pubchem.ncbi.nlm.nih.gov/rest/pug_view/data/compound/5282108/JSON/?response_type=display")

会给我一个嵌套列表树,但是我如何从这个相当复杂的嵌套列表列表转到一个不错的数据框或数据框列表?

在这种情况下,我所追求的就是下面的一切

3.1 计算描述符

3.2 其他标识符

3.3 同义词

4.1 计算属性

在数据框的单行中,每个元素在单独的命名列中,每个元素有多个项目(例如多个同义词),并用“|”粘贴在一起作为分隔符。例如。在这种情况下类似于

pubchemid      IUPAC_Name    InChI       InChI_Key     Canonical SMILES      Isomeric SMILES     CAS     EC Number     Wikipedia      MeSH Synonyms     Depositor-Supplied Synonyms   Molecular_Weight    Molecular_Formula    XLogP3   Hydrogen_Bond_Donor_Count ... 
5282108        (E)-4-(2,6,6-trimethylcyclohex-2-en-1-yl)but-3-en-2-one       InChI=1S/C13H20O/c1-10-6-5-9-13(3,4)12(10)8-7-11(2)14/h6-8,12H,5,9H2,1-4H3/b8-7+ ....

具有多个项目的字段,例如存款人提供的同义词可以用“|”粘贴在一起,例如值可能是 ALPHA-IONONE|Iraldeine|...

其次,我还要导入部分 4.2.2 Kovats 留存指数 作为数据框

pubchemid      column_class            kovats_ri
5282108        Standard non-polar      1413
5282108        Standard non-polar      1417
...
5282108        Semi-standard non-polar 1427
...

(第 4.3.1 节 GC-MS 本来也不错,但由于它只显示 3 个顶峰,所以现在有点没用,所以我会跳过它)

有人知道如何以优雅的方式实现这一目标吗?

PS 请注意,对于任何给定的查询,并非所有这些字段都必须存在。

二维结构和一些性质也可以从

https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/5282108/record/SDF/?record_type=2d&response_type=display

和 3D 结构来自

https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/5282108/record/SDF/?record_type=3d&response_type=display

数据也可以导出为 XML,使用

https://pubchem.ncbi.nlm.nih.gov/rest/pug_view/data/compound/5282108/XML/?response_type=display

如果这样会更容易

注意:也尝试使用 R 包 rpubchem,但似乎只导入了少量可用信息:

library("rpubchem")
get.cid(5282108)
CID  IUPACName CanonicalSmile MolecularFormula MolecularWeight TotalFormalCharge XLogP HydrogenBondDonorCount HydrogenBondAcceptorCount HeavyAtomCount    TPSA
2 5282108 (E)-4-(2,6,6-trimethylcyclohex-2-en-1-yl)but-3-en-2-one        C13H20O       192.297300               0                 3     0                      1                        14             17 5282108

【问题讨论】:

  • 您能否更具体地说明“所有内容”的确切含义?另外,您对预期 data.frame 的解释对我来说不是很清楚。您可以尝试手动创建示例(部分)行吗?我还建议将“Kovats Retention Index”放在自己的段落中,因为这对您来说似乎不是硬性要求。
  • 我做了一些澄清 - 希望现在更好?对于所有内容,我基本上是指为给定化合物提供的任何字段(这可能因化合物而异)......因此对于多个化合物,数据框仍然必须合并。

标签: json xml r xml-parsing pubchem


【解决方案1】:

我的建议适用于 XML 文件,因为(感谢 XPath)我发现它们更便于遍历和选择节点。

请注意,这既不快(测试时需要几秒钟)也不是最佳的(我对每个文件进行两次解析 - 一次用于名称等,一次用于 Kovats 保留索引)。但我猜你会想要解析一些文件集然后继续你的真正业务,而过早的优化是万恶之源。

我已将主要任务放入单独的功能中。如果您想获取一个特定的 pubchem 记录的数据,它们就可以使用了。但是,如果您想一次从几个 pubchem 记录中获取数据,您可以定义指向数据的指针向量并使用底部的示例将结果合并在一起。就我而言,vector 包含本地磁盘上文件的路径。也支持 URL,但我不鼓励它们(请记住,每个站点将被请求两次,如果记录数量更多,您可能希望以某种方式处理故障网络)。

您已链接到的化合物在“EC 编号”上有多个条目。它们确实有ReferenceNumber 的不同,但Name 没有区别。我不知道为什么会这样,我应该怎么做(你的示例输出只包含一个 EC 编号条目),所以我把它留给了 R。R 为重复值添加了后缀并创建了EC.Number.1,@ 987654324@ 等。这些后缀与文件中的ReferenceNumber 匹配,并且主数据框中的同一列可能会针对不同的化合物引用不同的ReferenceNumbers。

似乎 pubchem 对标签 &lt;type&gt;Value[List] 使用以下格式。在少数地方,我对StringValue 进行了硬编码,但也许某些化合物在同一字段中具有不同的类型。我通常不会考虑清单,除非是在要求的地方。因此,随着在此代码中抛出更多数据,可能需要进一步修改。

如果您有任何问题,请在 cmets 中发布。我不确定是否应该解释该代码或什么。

library("xml2")
library("data.table")

compound.attributes <- function(file=NULL) {
  compound <- read_xml(file)
  ns <- xml_ns(compound)
  information <- xml_find_all(compound, paste0(
    "//d1:TOCHeading[text()='Computed Descriptors'",
    " or text()='Other Identifiers'",
    " or text()='Synonyms'",
    " or text()='Computed Properties']",
    "/following-sibling::d1:Section/d1:Information"
  ), ns)

  properties <- sapply(information, function(x) {
    name <- xml_text(xml_find_one(x, "./d1:Name", ns))
    value <- ifelse(length(xml_find_all(x, "./d1:StringValueList", ns)) > 0,
                    paste(sapply(
                      xml_find_all(x, "./d1:StringValueList", ns),
                      xml_text, trim=TRUE), sep="", collapse="|"),
                    xml_text(
                      xml_find_one(x, "./*[contains(name(),'Value')]", ns),
                      trim=TRUE)
    )
    names(value) <- name
    return(value)
  })
  rm(compound, information)
  properties <- as.list(properties)
  properties$pubchemid <- sub(".*/([0-9]+)/?.*", "\\1", file)
  return(data.frame(properties))
}

compound.retention.index <- function(file=NULL) {
  pubchemid <- sub(".*/([0-9]+)/?.*", "\\1", file)
  compound <- read_xml(file)
  ns <- xml_ns(compound)
  information <- xml_find_all(compound, paste0(
    "//d1:TOCHeading[text()='Kovats Retention Index']",
    "/following-sibling::d1:Information"
  ), ns)
  indexes <- lapply(information, function(x) {
    name <- xml_text(xml_find_one(x, "./d1:Name", ns))
    values <- as.numeric(sapply(
      xml_find_all(x, "./*[contains(name(), 'NumValue')]", ns), 
      xml_text))

    data.frame(pubchemid=pubchemid,
               column_class=name,
               kovats_ri=values)
  })

  return( do.call("rbind", indexes) )
}

compounds <- c("./5282108.xml", "./5282148.xml", "./91754124.xml")

cd <- rbindlist(
  lapply(compounds, compound.attributes),
  fill=TRUE
)

rti <- do.call("rbind",
               lapply(compounds, compound.retention.index))

【讨论】:

  • 哈,非常感谢!这正是我想要的!很高兴您将 xml2 与 XML 包一起使用,我也遇到了内存泄漏问题!
  • @Mirosław Zalewski 请知道如何使用相同的概念在 pubchem 中检索给定 CID 的 ATC 代码?
  • @aliocee 请将此作为单独的问题提出。评论是为了更正、澄清和其他简短的评论。它们不适用于询问和回答类似于主要问题的问题。
  • @MirosławZalewski 关于这个问题的问题,一些 标签有 StringValue 而不是 StringValueList 我们如何提取'properties'中的那些?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
相关资源
最近更新 更多