Кодировка текста UTF-8/Unicode с помощью RPostgreSQL

Я запускаю R на компьютере с Windows, который напрямую связан с базой данных PostgreSQL. Я не использую RODBC. Моя база данных закодирована в UTF-8, что подтверждается следующей командой R:

dbGetQuery(con, "SHOW CLIENT_ENCODING")
#   client_encoding
# 1            UTF8

Однако когда некоторый текст считывается в R, он отображается как странный текст в R.

Например, в моей базе данных PostgreSQL отображается следующий текст: «Стефан».

После экспорта в R это отображается как: "Stéphane" (é кодируется как é)

При импорте в R я использую команду dbConnect для установки соединения и команду dbGetQuery для запроса данных с помощью SQL. Я нигде не указываю кодировку текста ни при подключении к базе данных, ни при выполнении запроса.

Я искал в Интернете и не могу найти прямого решения моей проблемы. Я нашел эту ссылку, но их проблема связана с RODBC, которую я не используя.

Эта ссылка помогает идентифицировать символы, но я не хочу просто выполнить поиск и замену в R... слишком много данных.

Я попытался запустить следующие команды ниже и получил предупреждение.

Sys.setlocale("LC_ALL", "en_US.UTF-8")
# [1] ""
# Warning message:
# In Sys.setlocale("LC_ALL", "en_US.UTF-8") :
#   OS reports request to set locale to "en_US.UTF-8" cannot be honored
Sys.setenv(LANG="en_US.UTF-8")
Sys.setenv(LC_CTYPE="UTF-8")

Предупреждение появляется по команде Sys.setlocale("LC_ALL", "en_US.UTF-8"). Моя интуиция подсказывает, что это проблема, специфичная для Windows, и не возникает с Mac/Linux/Unix.


person David L    schedule 27.01.2014    source источник
comment
Обратите внимание, что client_encoding не является фактической кодировкой, используемой вашей базой данных. Кодировку базы данных можно найти с помощью параметра psql -l или команды \l.   -  person nwellnhof    schedule 28.01.2014


Ответы (5)


После экспорта в R он отображается как: «Stéphane» (é кодируется как é)

В вашей среде R используется 1-байтовая несложенная кодировка, такая как latin-1 или windows-1252. Взгляните на этот тест на Python, демонстрирующий, что байты utf-8 для é, декодированные так, как если бы они были latin-1, создают текст, который вы видите:

>>> print u"é".encode("utf-8").decode("latin-1")
é

Либо SET client_encoding = 'windows-1252', либо исправьте кодировку, используемую вашей средой R. Если он работает в консоли cmd.exe, вам придется возиться с консольной командой chcp; в противном случае это зависит от вашей среды выполнения R.

person Craig Ringer    schedule 28.01.2014
comment
Да, это работает. Я выполнил команду postgresqlpqExec(con, "SET client_encoding = 'windows-1252'") перед загрузкой данных из PostgreSQL, и хотя система возвращает FALSE, она все равно преобразуется в нужный символ. Спасибо! - person David L; 29.01.2014
comment
@DavidL Просто имейте в виду, что если вы выберете этот подход и ваши данные будут содержать символы, которые не могут быть представлены в Windows-1252, запросы будут завершаться ошибкой кодирования. Если возможно, было бы лучше использовать для среды R использование Unicode. - person Craig Ringer; 30.01.2014
comment
Как вместо этого настроить среду R, используя Unicode? - person Peter.k; 25.01.2018

Как сказал Крейг Рингер, установка client_encoding на windows-1252, вероятно, не лучший выход. Действительно, если данные, которые вы извлекаете, содержат один экзотический символ, у вас проблемы:

Ошибка в postgresqlExecStatement(conn, statement,...): Драйвер RS-DBI: (не удалось получить результат: ОШИБКА: символ 0xcca7 кодировки «UTF8» не имеет эквивалента в «WIN1252»)

С другой стороны, заставить вашу среду R использовать Unicode может быть невозможно (у меня та же проблема, что и у вас, с Sys.setlocale... То же самое в этот вопрос тоже.).

Обходной путь — вручную объявить кодировку UTF-8 для всех ваших данных, используя функцию, подобную этой:

set_utf8 <- function(x) {
  # Declare UTF-8 encoding on all character columns:
  chr <- sapply(x, is.character)
  x[, chr] <- lapply(x[, chr, drop = FALSE], `Encoding<-`, "UTF-8")
  # Same on column names:
  Encoding(names(x)) <- "UTF-8"
  x
}

И вы должны использовать эту функцию во всех ваших запросах:

set_utf8(dbGetQuery(con, "SELECT myvar FROM mytable"))

EDIT: Другой вариант — использовать RPostgres вместо RPostgreSQL. Я протестировал его (с той же конфигурацией, что и в вашем вопросе), и, насколько я вижу, все объявленные кодировки автоматически устанавливаются в UTF-8.

person Scarabee    schedule 27.01.2017
comment
Я могу подтвердить, что использование RPostgres решает проблему. - person moj; 05.06.2018
comment
Как Postgres, так и решения set_utf8 работали очень хорошо. - person Fabio Correa; 24.04.2021

Если вы используете RPostgres::Postgres() в качестве первого параметра dbConnect(), обычно у вас не будет проблем с кодировкой.

Я попробовал этот скрипт, где у меня была та же проблема, и теперь мои акцентированные символы в порядке.

dbConnect(RPostgres::Postgres(),user="user",password="psw",host="host",port=5432,dbname="db_name")
person Guillaume Doucet    schedule 30.03.2020

Это устранит любые проблемы с Unicode/UTF-8 в Windows. Он должен быть выполнен перед запросом к базе данных.

postgresqlpqExec(con, "SET client_encoding = 'windows-1252'")

Взято из неуместного самостоятельного ответа спрашивающего, видно в истории изменений вопроса

person Community    schedule 13.05.2017
comment
@Scarabee: я проверил перед публикацией, и у Крейга было меньше подробностей об этом, упомянув только, что должен быть какой-то способ, специфичный для среды выполнения R, для установки client_encoding. - person Nathan Tuggy; 13.05.2017

person    schedule
comment
Я получаю сообщение об ошибке в postgresqlNewConnection(drv,...): неиспользуемый аргумент (кодировка = latin1) - person Fato39; 30.03.2020