Skip to content

Instantly share code, notes, and snippets.

@artemklevtsov
Last active December 12, 2019 11:15
Show Gist options
  • Save artemklevtsov/60a4d63b911791d7f1cc7fd3dc489e85 to your computer and use it in GitHub Desktop.
Save artemklevtsov/60a4d63b911791d7f1cc7fd3dc489e85 to your computer and use it in GitHub Desktop.
#' @title Перекодировка столбцов таблицы
#' @param x Вектор или таблица.
#' @param enc Строка, содержащая название кодировки. Если параметр не задан, используется автоопределение кодировки.
#' @param defqult Строка, содержащая кодировку по умолчанию, которая будет использована в случае, если автоматически определить кодировку не удалось.
#' @return Исходный объект, с перекодированными элементами.
#' @details
#' Функция изменяет объект на месте, то есть будет изменён переданный объект.
#' Для определения кодировки используется пакет `Ruchardet`.
#' Предполагается, что вектор (столбец) содердит только одну кодировку.
#' @importFrom data.table set setDT
#' @importFrom uchardet detect_str_enc
#' @importFrom stringi stri_enc_mark stri_encode
#' @author Artem Klevtsov
convert_encoding <- function(x, ...) {
UseMethod("convert_encoding")
}
convert_encoding.default <- function(x, ...) {
stop("Not implemented. Please implement S3-method for the appropriate class.")
}
convert_encoding.character <- function(x, enc, default = "CP1251") {
# Находим индексы вектора с нативной кодировкой
ind <- which(stringi::stri_enc_mark(x) == "native")
# Перекодируем только, если есть элементы в нативной кодировке
if (length(ind) > 0L) {
# Если кодировка не указана
if (missing(enc)) {
# Копируем элементы в нативной кодировке во временный вектор
tmp <- paste(x[ind], collapse = " ")
# Определяем кодировку
enc <- uchardet::detect_str_enc(tmp)
if (is.na(enc)) {
warning("Не удалось определить кодировку элементов, считаем по умолчанию ", default)
enc <- default
}
}
x[ind] <- stringi::stri_encode(x[ind], enc, "UTF-8")
}
return(x)
}
convert_encoding.data.table <- function(x, enc, default = "CP1251") {
# Преобразуем в `data.table` при необходимости
if (!is.data.table(x)) setDT(x)
# Перекодируем имена столбцов
setnames(x, convert_encoding(names(x), enc = enc, default = default))
# Автоматически определяем character-столбцы
cols <- which(sapply(x, is.character), useNames = FALSE)
# Если список столбцов пустой, выходим
if (length(cols) == 0L)
return(invisible(NULL))
# Цикл в данном случае также быстр как и lapply(.SD, ...), но более экономичен по памяти
for (col in cols)
set(x, j = col, value = convert_encoding(x[[col]], enc = enc, default = default))
return(invisible(x))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment