如何在R中识别/删除非UTF-8字符

41
当我在R中导入Stata数据集(使用foreign包),导入有时会包含无效的UTF-8字符。这本身就很不愉快,但一旦我尝试将对象转换为JSON(使用rjson包),就会导致一切崩溃。
我该如何识别字符串中的非有效UTF-8字符,并在此之后将它们删除?
4个回答

47

使用iconv函数的另一种解决方案,其中的参数sub是字符字符串。如果不是NA(我在这里将其设置为空),则用它来替换输入中任何无法转换的字节。

x <- "fa\xE7ile"
Encoding(x) <- "UTF-8"
iconv(x, "UTF-8", "UTF-8",sub='') ## replace any non UTF-8 by ''
"faile"

需要注意的是,如果我们选择正确的编码方式:

x <- "fa\xE7ile"
Encoding(x) <- "latin1"
xx <- iconv(x, "latin1", "UTF-8",sub='')
facile

8

Yihui的xfun包有一个名为read_utf8的函数,该函数尝试读取文件并假设它以UTF-8编码。如果文件包含非UTF-8行,则会触发警告,让您知道哪些行包含非UTF-8字符。在底层,它使用一个未导出的函数xfun:::invalid_utf8(),其代码如下:which(!is.na(x) & is.na(iconv(x, "UTF-8", "UTF-8")))

要在字符串中检测特定的非UTF-8单词,可以稍微修改上述内容,并执行以下操作:

invalid_utf8_ <- function(x){

  !is.na(x) & is.na(iconv(x, "UTF-8", "UTF-8"))

}

detect_invalid_utf8 <- function(string, seperator){

  stringSplit <- unlist(strsplit(string, seperator))

  invalidIndex <- unlist(lapply(stringSplit, invalid_utf8_))

  data.frame(
    word = stringSplit[invalidIndex],
    stringIndex = which(invalidIndex == TRUE)
  )

}

x <- "This is a string fa\xE7ile blah blah blah fa\xE7ade"

detect_invalid_utf8(x, " ")

#     word stringIndex
# 1 façile    5
# 2 façade    9

4

使用dplyr在整个数据集上删除不良字符的另一种方法:

library(dplyr)

MyDate %>%
    mutate_at(vars(MyTextVar1, MyTextVar2), function(x){gsub('[^ -~]', '', x)})

其中MyDataMyTextVar是数据集和文本变量,用于清除不良苹果。这种方法可能不如更改编码稳健,但通常情况下可以轻松解决问题,只需将其删除即可。


5
基于Tyler的回答,您可以考虑使用MyDate %>% mutate_if(is.character, ~gsub('[^ -~]', '', .)),它针对所有字符列,或者使用MyData %>% mutate_all(~gsub('[^ -~]', '', .)),它针对所有列。 - sbha
4
这个操作移除了比需要更多的字符。问题要求的是非UTF8,而不是非ASCII。 - user3932000

2

你可以尝试使用iconv将它们转换为UTF-8字符串,而不是删除它们。

require(foreign)
dat <- read.dta("data.dta")

for (j in seq_len(ncol(dat))) {
   if (class(dat[, j]) == "factor")
       levels(dat[, j]) <- iconv(levels(dat[, j]), from = "latin1", to = "UTF-8")
}

你可以根据实际情况将latin1替换为更合适的编码方式。由于我们无法访问您的数据,因此很难确定哪种编码方式更合适。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接