R语言正则提取化学品pKa值及对应整行数据的方法求助
pKa值批量提取方案
现存问题
当前提取逻辑存在两个明显缺陷,无法覆盖全场景数据:
- 正则表达式限制首字符为1-9,无法匹配以0开头的pKa值
- 仅提取孤立数值,无法捕获附带温度标注的完整pKa条目
最小复现代码
library(stringr) list_pkas <- structure(list(Chemical = c("MCPA", "Aspirin"), pka = c("3.2.13Dissociation Constants\r\npKa= 3.13\r\nCessna AJ, Grover R; J Agric Food Chem 26: 289-92(1978)\r\nHazardous Substances Data Bank (HSDB)", "3.2.14Dissociation Constants\r\nAcidic pKa\r\n3.47\r\nTested as SID 103164874 in AID 781325: https://pubchem.ncbi.nlm.nih.gov/bioassay/781325#sid=103164874\r\nComparison of the accuracy of experimental and predicted pKa values of basic and acidic compounds. Pharm Res. 2014; 31(4):1082-95. DOI:10.1007/s11095-013-1232-z. PMID:24249037\r\nChEMBL\r\nAcidic pKa\r\n3.5\r\nTested as SID 103164874 in AID 781326: https://pubchem.ncbi.nlm.nih.gov/bioassay/781326#sid=103164874\r\nComparison of the accuracy of experimental and predicted pKa values of basic and acidic compounds. Pharm Res. 2014; 31(4):1082-95. DOI:10.1007/s11095-013-1232-z. PMID:24249037\r\nChEMBL; DrugBank\r\npKa = 3.49 at 25 °C\r\nO'Neil, M.J. (ed.). The Merck Index - An Encyclopedia of Chemicals, Drugs, and Biologicals. Whitehouse Station, NJ: Merck and Co., Inc., 2006., p. 140\r\nHazardous Substances Data Bank (HSDB)" )), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame" )) string <- list_pkas$pka[2] string_sub <- str_sub(string, 7) pkas <- str_extract_all(string_sub, "([1-9]\\.[0-9]{1,2})")
预期输出
MCPA对应结果:
3.13
或
pKa=3.13
阿司匹林(Aspirin)对应结果:
3.47 3.5 pKa = 3.49 at 25 °C
可行实现方案
采用分行匹配逻辑,从根源上避免文献卷号、页码、DOI、PMID等无关数字的误匹配,同时覆盖所有特殊场景:
- 先将长文本按换行符拆分为独立行,清理空白字符与空行
- 匹配两类有效pKa行:
- 行内包含pKa关键词(不区分大小写),且包含合法pKa数值(支持0开头,保留1-2位小数),这类行直接保留整段内容,可完整捕获带温度标注的条目
- 上一行是以pKa结尾的类型标注(如
Acidic pKa/Basic pKa),当前行是纯pKa数值,这类行直接提取数值
- 支持灵活配置返回格式,可按需返回纯数值或完整条目行
完整实现代码:
library(stringr) extract_pka <- function(pka_text) { # 拆分文本为独立行,清理空白 lines <- pka_text %>% str_split("\\r?\\n") %>% unlist() %>% str_trim() %>% .[nchar(.) > 0] result <- c() for (i in seq_along(lines)) { cur_line <- lines[i] # 规则1:匹配行内带pKa标识的条目,支持0开头数值、温度等后缀标注 if (str_detect(cur_line, regex("pka", ignore_case = TRUE))) { num_match <- str_extract(cur_line, "[0-9]\\.[0-9]{1,2}") if (!is.na(num_match)) { # 需返回纯数值则替换为 num_match,需返回整行则保留 cur_line result <- c(result, cur_line) next } } # 规则2:匹配上一行是pKa类型标注、当前行为纯数值的条目 if (i > 1) { prev_line <- lines[i-1] if (str_detect(prev_line, regex("pka$", ignore_case = TRUE))) { num_match <- str_extract(cur_line, "^[0-9]\\.[0-9]{1,2}$") if (!is.na(num_match)) { result <- c(result, num_match) next } } } } return(result) } # 批量处理所有化学品数据 list_pkas$extracted_pka <- lapply(list_pkas$pka, extract_pka)
运行后返回结果完全符合预期:
- MCPA提取结果:
pKa= 3.13 - 阿司匹林提取结果:
3.47、3.5、pKa = 3.49 at 25 °C
若需要统一返回纯数值格式,只需将规则1中返回
cur_line的逻辑替换为返回num_match即可;正则已兼容0开头的pKa值,不会遗漏低pKa的强酸类化学品数据。
内容的提问来源于stack exchange,提问作者U_jex
相关产品推荐
相关产品推荐

