我有一个 R 包,其中有一个大学名称列表,我想将其与用户输入相匹配。名称列表包含特殊字符,这会在 R CMD 检查中生成警告:
checking data for non-ASCII characters (855ms)
Warning: found non-ASCII strings
现在,我正在将这些非 ASCII unicode 字符转换为符合 ASCII 的转义版本,以使用
stringi::stri_escape_unicode()
消除此警告。然而,现在我在其他函数中所需的 grepl 似乎没有按预期工作:
用户提供带有重音符号的文本(例如“é”),我将其与我的数据库进行匹配。但它似乎没有正确检测字符串:
a <- stringi::stri_escape_unicode("é")
a == "é"
#> [1] FALSE
a == "\\é"
#> [1] FALSE
grepl("é", a)
#> [1] FALSE
创建于 2023-09-03,使用 reprex v2.0.2
注:后续this。
大学列表在此处创建:https://github.com/rempsyc/pubmedDashboard/blob/master/data-raw/universities.R
但现在我意识到(感谢您在评论中指出这一方面),当我对大学名称和附属地址进行比较时,我使用
easyPubMed
的输出,它实际上似乎使用了不同的编码(尽管默认编码)应该使用UTF8)。
在 RStudio 查看器中,将鼠标悬停在附属地址上时,它看起来像这样,例如“Département de Psychologie, Université du Québec à Montréal, Montréal”。
然而,它似乎实际上是这样编码的(编辑:即使在 stackoverflow 上,符号也被正确渲染,所以我必须将它们作为代码):
"Département de Psychologie, Université du Québec à Montréal, Montréal"
我意识到这可能就是比较不起作用的原因:
"é" == "é"
#> [1] FALSE
创建于 2023-09-03,使用 reprex v2.0.2
我的错误是假设我在 RStudio 中使用鼠标悬停时看到的是真实的角色,而在幕后却是不同的东西。
据我所知,这种编码形式对应于 Unicode 十六进制字符代码。我需要的可能是
stringi
中的另一个函数,用于从 Unicode 十六进制字符代码转换为常规编码。
这是
easyPubMed
包提供的地址从属关系的表示:
library(easyPubMed)
dami_query_string <- "Dualistic Model of Passion [Text Word] AND ('2023/01/01' [Date - Publication] : '2023/12/31' [Date - Publication])"
dami_on_pubmed <- get_pubmed_ids(dami_query_string)
pubmed_data <- fetch_pubmed_data(dami_on_pubmed)
dami_abstracts_list <- articles_to_list(pubmed_data)
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
但是由于
article_to_df
内部的错误,完整的地址没有显示。为此,我们必须使用pubmedDashboard
的版本:
# remotes::install_github("rempsyc/pubmedDashboard")
library(pubmedDashboard)
article_to_df2(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Département de Psychologie, Université du Québec à Montréal, Montréal, QC H3C 3P8, Canada."
创建于 2023-09-03,使用 reprex v2.0.2
检测到的编码是什么?
stringi::stri_enc_detect("é")
#> [[1]]
#> Encoding Language Confidence
#> 1 UTF-8 0.15
#> 2 UTF-16BE 0.10
#> 3 UTF-16LE 0.10
创建于 2023-09-03,使用 reprex v2.0.2
这个网站转换似乎可以解决问题,但我无法用
stringi
... 做同样的事情
代表:
stringi::stri_encode("é", from = "UTF8", to = "ASCII")
#> [1] "é"
stringi::stri_encode("é", from = "UTF16", to = "ASCII")
#> Warning in stringi::stri_encode("é", from = "UTF16", to = "ASCII"): the
#> Unicode code point \U00002623 cannot be converted to destination encoding
#> Warning in stringi::stri_encode("é", from = "UTF16", to = "ASCII"): the
#> Unicode code point \U00007865 cannot be converted to destination encoding
#> Warning in stringi::stri_encode("é", from = "UTF16", to = "ASCII"): the
#> Unicode code point \U0000393b cannot be converted to destination encoding
#> [1] "\032\032\032"
stringi::stri_encode("é", from = "Hex", to = "ASCII")
#> Error in stringi::stri_encode("é", from = "Hex", to = "ASCII"): The requested ICU resource file cannot be found. (U_FILE_ACCESS_ERROR)
创建于 2023-09-03,使用 reprex v2.0.2
stringi::stri_unescape_unicode("é")
#> [1] "é"
创建于 2023-09-03,使用 reprex v2.0.2
easyPubMed
我在想,也许如果我可以直接从 easyPubMed 更改编码,那会让我的生活更轻松。根据包文档这是可能的:
请注意,我们包含一个参数(即编码)来强制对检索到的记录进行编码。这里,我们推荐“UTF8”。但是,您可以选择不同的编码(取决于本地平台)。例如,这里我们指定编码=“ASCII”。
但似乎我无法正确执行十六进制:
library(easyPubMed)
dami_query_string <- "Dualistic Model of Passion [Text Word] AND ('2023/01/01' [Date - Publication] : '2023/12/31' [Date - Publication])"
dami_on_pubmed <- get_pubmed_ids(dami_query_string)
pubmed_data <- fetch_pubmed_data(dami_on_pubmed)
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "ASCII")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "UTF8")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "UTF16")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "latin")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "unicode")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
dami_abstracts_list <- articles_to_list(pubmed_data, encoding = "hex")
article_to_df(dami_abstracts_list[[5]])$address[1]
#> [1] "Laboratoire de Recherche sur le Comportement Social, Dé"
创建于 2023-09-03,使用 reprex v2.0.2
第一步,我们必须定义一个新函数来将十六进制字符转换为常规文本:
convert_hex_to_char <- function(hex_string) {
# Extract all hex codes from the string using stringi::stri_extract_all_regex
hex_codes <- stringi::stri_extract_all_regex(hex_string, "&#x[0-9a-fA-F]+;")[[1]]
# Convert hex codes to characters
chars <- lapply(hex_codes, function(hex_code) {
int_val <- strtoi(gsub("&#x(.*);", "\\1", hex_code), base=16)
char <- intToUtf8(int_val)
return(char)
})
chars <- as.character(chars)
# Replace hex codes with characters in the original string
for (i in seq_along(hex_codes)) {
hex_string <- sub(hex_codes[i], chars[i], hex_string)
}
return(hex_string)
}
# Test the function
sentence <- "Département de Psychologie, Université du Québec à Montréal, Montréal"
converted_sentence <- convert_hex_to_char(sentence)
converted_sentence
#> [1] "Département de Psychologie, Université du Québec à Montréal, Montréal"
但是,将十六进制字符转换为常规文本是不够的,因为即使这样也无法匹配转义的 unicode。因此,我们需要对大学名称进行转义(在下面的示例中进行了简化):
pattern <- stringi::stri_unescape_unicode(stringi::stri_escape_unicode("Université"))
grepl(pattern, converted_sentence)
#> [1] TRUE
注意:感谢 ChatGPT 提供此功能。几乎可以肯定有一个现有的函数或包可以做到这一点,我将接受具有此类解决方案的另一个答案。
创建于 2023-09-03,使用 reprex v2.0.2