Как идентифицировать/удалить символы не UTF-8 в R

Когда я импортирую набор данных Stata в R (используя пакет foreign), импорт иногда содержит недопустимые символы UTF-8. Само по себе это достаточно неприятно, но все ломается, как только я пытаюсь преобразовать объект в JSON (используя пакет rjson).

Как я могу определить недействительный- UTF-8 -characters в строке и удалить их после этого?

Ответ 1

Другое решение, использующее 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

Ответ 2

Вместо их удаления вы можете попытаться преобразовать их в строку UTF-8, используя iconv.

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 на более подходящее приложение в вашем случае. Поскольку у нас нет доступа к вашим данным, трудно понять, какой из них будет более подходящим.

Ответ 3

Другой подход для удаления плохих символов с использованием dplyr для всего набора данных:

library(dplyr)

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

Где MyData и MyTextVar - набор данных и текстовые переменные для удаления плохих парней. Это может быть менее надежно, чем изменение кодировки, но часто бывает проще и проще их просто удалить.

Ответ 4

Пакет 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