29

I am trying to import a CSV encoded as OEM-866 (Cyrillic charset) into R on Windows. I also have a copy that has been converted into UTF-8 w/o BOM. Both of these files are readable by all other applications on my system, once the encoding is specified.

Furthermore, on Linux, R can read these particular files with the specified encodings just fine. I can also read the CSV on Windows IF I do not specify the "fileEncoding" parameter, but this results in unreadable text. When I specify the file encoding on Windows, I always get the following errors, for both the OEM and the Unicode file:

Original OEM file import:

> oem.csv <- read.table("~/csv1.csv", sep=";", dec=",", quote="",fileEncoding="cp866")   #result:  failure to import all rows
Warning messages:
1: In scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  :
  invalid input found on input connection '~/Revolution/RProject1/csv1.csv'
2: In scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  :
  number of items read is not a multiple of the number of columns

UTF-8 w/o BOM file import:

> unicode.csv <- read.table("~/csv1a.csv", sep=";", dec=",", quote="",fileEncoding="UTF-8") #result:    failure to import all row
Warning messages:
1: In scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  :
  invalid input found on input connection '~/Revolution/RProject1/csv1a.csv'
2: In scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  :
  number of items read is not a multiple of the number of columns

Locale info:

> Sys.getlocale()
   [1] "LC_COLLATE=English_United States.1252;LC_CTYPE=English_United States.1252;LC_MONETARY=English_United States.1252;LC_NUMERIC=C;LC_TIME=English_United States.1252"

What is it about R on Windows that is responsible for this? I've pretty much tried everything I could by this point, besides ditching windows.

Thank You

(Additional failed attempts):

>Sys.setlocale("LC_ALL", "en_US.UTF-8") #OS reports request to set locale to "en_US.UTF-8" cannot be honored
>options(encoding="UTF-8") #now nothing can be imported  
> noarg.unicode.csv <- read.table("~/Revolution/RProject1/csv1a.csv", sep=";", dec=",", quote="")   #result: mangled cyrillic
> encarg.unicode.csv <- read.table("~/Revolution/RProject1/csv1a.csv", sep=";", dec=",", quote="",encoding="UTF-8") #result: mangled cyrillic
4

5 回答 5

8

您的问题可能通过将 fileEncoding 更改为 encoding 来解决,这些参数在 read 函数中的工作方式不同(请参阅 ?read)。

oem.csv <- read.table("~/csv1.csv", sep=";", dec=",", quote="",encoding="cp866")

但是,以防万一,一个更完整的答案,因为可能存在一些不明显的障碍。简而言之:可以在 Windows 上使用 R 中的 Cyrillic(在我的情况下为 Win 7)。

您可能需要尝试一些可能的编码才能使事情正常工作。对于文本挖掘,一个重要的方面是让您的输入变量与数据相匹配。Encoding() 的功能非常有用,参见 iconv()。因此可以看到您的本机参数。

Encoding(variant <- "Минемум")

在我的情况下,编码是 UTF-8,尽管这可能取决于系统设置。因此,我们可以尝试使用 UTF-8 和 UTF-8-BOM 的结果,并在 notepad++ 中制作一个包含一行拉丁文和一行西里尔文的测试文件。

UTF8_nobom_cyrillic.csv & UTF8_bom_cyrillic.csv

part2, part3, part4
Минемум конкыптам, тхэопхражтуз, ед про

这可以通过

raw_table1 <- read.csv("UTF8_nobom_cyrillic.csv", header = FALSE, sep = ",", quote = "\"", dec = ".", fill = TRUE, comment.char = "", encoding = "UTF-8")
raw_table2 <- read.csv("UTF8_bom_cyrillic.csv", header = FALSE, sep = ",", quote = "\"", dec = ".", fill = TRUE, comment.char = "", encoding = "UTF-8-BOM")

这些结果对我来说是视图中的 BOM 常规西里尔字母(raw_table1)和控制台中的乱码。

part2, part3, part4
ŠŠøŠ½ŠµŠ¼ŃŠ¼ ŠŗŠ¾Š½ŠŗŃ‹ŠæŃ‚Š°Š¼ тхѨŠ¾ŠæŃ…Ń€Š°Š¶Ń‚ŃŠ

然而,更重要的是,该脚本无法访问它。

> grep("Минемум", as.character(raw_table2[2,1]))
integer(0)

No BOM UTF-8 的结果对于视图(raw_table1)和控制台都是这样的。

part2, part3, part4
<U+041C><U+0438><U+043D><U+0435><U+043C><U+0443><U+043C> <U+043A><U+043E><U+043D><U+043A><U+044B><U+043F><U+0442><U+0430><U+043C> <U+0442><U+0445><U+044D><U+043E><U+043F><U+0445><U+0440><U+0430><U+0436><U+0442><U+0443><U+0437> <U+0435><U+0434> <U+043F><U+0440><U+043E>

然而,重要的是,搜索里面的单词会产生正确的结果。

> grep("Минемум", as.character(raw_table1[2,1]))
1

因此,可以在 Windows 中使用非标准字符,但这取决于您的确切目标。我经常使用非英语拉丁字符,UTF-8 允许在 Windows 7 中正常工作。“WINDOWS-1252”对于导出到 Excel 等 Microsoft 阅读器非常有用。

PS 俄语单词是在这里生成的http://generator.lorem-ipsum.info/_russian,所以基本上没有意义。PPS 您提到的警告仍然没有明显的重要影响。

于 2015-02-11T18:19:07.773 回答
7

简单的回答。

Sys.setlocale(locale = "Russian")

如果您只想要俄语(不是格式,货币):

'Sys.setlocale(category = "LC_COLLATE", locale = "Russian")'

'Sys.setlocale(category = "LC_CTYPE", locale = "Russian")'

如果碰巧使用的是 Revolution R Open 3.2.2,您可能还需要在控制面板中设置区域设置:否则 - 如果您有 RStudio - 您将在查看器中看到西里尔文文本并在控制台中看到垃圾。因此,例如,如果您键入一个随机的西里尔字符串并按回车键,您将得到垃圾输出。有趣的是,Revolution R 在说阿拉伯语文本时没有同样的问题。如果您使用常规 R,似乎Sys.setlocale()就足够了。

'Sys.setlocale()' 是由用户 G. Grothendieck 建议的:R、Windows 和外语字符

于 2015-12-13T21:13:22.023 回答
6

从包含当前语言环境不支持的字符的文件中读取数据有两种选择。您可以按照@user23676 的建议更改您的语言环境,也可以转换为 UTF-8。该包为您执行此转换的派生函数readr提供了替换。read.table您可以使用以下命令读取 CP866 文件

library(readr)
oem.csv <- read_csv2('~/csv1.csv', locale = locale(encoding = 'CP866'))

有一个小问题,即存在一个错误print.data.frame,导致使用 UTF-8 编码的列在 Windows 上显示不正确。您可以使用print.listof(oem.csv)或解决该错误print(as.matrix(oem.csv))

我在http://people.fas.harvard.edu/~izahn/posts/reading-data-with-non-native-encoding-in-r/的博客文章中对此进行了更详细的讨论

于 2016-06-19T00:16:20.800 回答
4

我认为这里有很多很好的答案,也有很多重复。我尝试提供更完整的问题描述以及我使用上述解决方案的方式。

我的情况 - 将 Google Translate API 的结果写入 R 中的文件

出于我的特殊目的,我将文本发送到 Google API:

   # load library
   library(translateR)

   # return chinese tranlation
   result_chinese <- translate(content.vec = "This is my Text",
                            google.api.key = api_key, 
                            source.lang = "en",
                            target.lang = "zh-CN")

我在中看到的结果R Environment是这样的:

在 R 环境中看到的翻译结果

但是,如果我在控制台中打印我的变量,我会看到这个格式很好(我希望)的文本:

> print(result_chinese)
[1] "这是我的文字"

在我的情况下,我必须使用 R 函数将文件写入计算机文件系统write.table()......但我要写的任何内容都将采用以下格式:

在 R 环境中看到的翻译结果

我的解决方案 - 取自上述答案:

我决定实际使用Sys.setlocale()这样的功能:

Sys.setlocale(locale = "Chinese") # set locale to Chinese

> Sys.setlocale(locale = "Chinese") # set locale to Chinese
[1] "LC_COLLATE=Chinese (Simplified)_People's Republic of China.936;LC_CTYPE=Chinese (Simplified)_People's Republic of China.936;LC_MONETARY=Chinese (Simplified)_People's Republic of China.936;LC_NUMERIC=C;LC_TIME=Chinese (Simplified)_People's Republic of China.936"

之后,我的翻译在 R 环境中正确可视化:

# return chinese tranlation with new locale 
result_chinese <- translate(content.vec = "This is my Text",
                            google.api.key = api_key, 
                            source.lang = "en",
                            target.lang = "zh-CN")

R环境中的结果是:

在 R 环境中正确可视化翻译

之后我可以写我的文件,最后看到中文文本:

# writing 
write.table(result_chinese, "translation.txt")

从记事本++看到的正确可视化和写入的文件

最后在我的翻译功能中,我将返回到我的原始设置:

Sys.setlocale() # to set up current locale to be default of the system

> Sys.setlocale() # to set up current locale to be default of the system
[1] "LC_COLLATE=English_United Kingdom.1252;LC_CTYPE=English_United Kingdom.1252;LC_MONETARY=English_United Kingdom.1252;LC_NUMERIC=C;LC_TIME=English_United Kingdom.1252"

我的结论:

在处理 R 中的特定语言之前:

  1. 将语言环境设置为特定语言的语言环境 Sys.setlocale(locale = "Chinese") # set locale to Chinese
  2. 执行所有数据操作
  3. 返回到您的原始设置 Sys.setlocale() # set original system settings
于 2017-12-21T18:32:07.640 回答
2

根据维基百科

字节顺序标记 (BOM) 是一个 Unicode 字符,用于表示字节顺序(字节顺序)[...] Unicode 标准允许 UTF-8 中的 BOM,但不要求也不推荐使用它。

无论如何,在 Windows 世界中,UTF8 与 BOM 一起使用。例如,标准记事本编辑器在保存为 UTF-8 时使用 BOM。

许多诞生于 Linux 世界的应用程序(包括 LaTex,例如在使用inputenc带有utf8.

Notepad++ 是从编码类型、Linux/DOS/Mac 行结尾和删除 BOM 转换的典型选项。

众所周知,BOM 的 UTF-8 非推荐表示是字节序列

0xEF,0xBB,0xBF

在文本流的开头,为什么不使用 R 本身将其删除?

## Converts an UTF8 BOM file as a NO BOM file
## ------------------------------------------

## Usage:
## Set the variable BOMFILE (file to convert) and execute

BOMFILE="C:/path/to/BOM-file.csv"


conr= file(BOMFILE,  "rb")
if(readChar(conr, 3, useBytes = TRUE)== ""){
    cat("The file appears UTF8-BOM. Converting as NO BOM.\n\n") 
    BOMFILE=sub("(\\.\\w*$)", "-NOBOM\\1", BOMFILE)
    BOMFILE=paste0( getwd(), '/', basename (BOMFILE))

    if(file.exists(BOMFILE)){
        cat(paste0('File:\n', BOMFILE, '\nalready exists. Please rename.\n' ))  
    } else{

    conw= file(BOMFILE,  "wb")
        while(length( x<-readBin(conr, "raw", n=100)) !=0){
            cat (rawToChar (x))
            writeBin(x, conw)  
    }
    cat(paste0('\n\nFile was converted as:\n', getwd(), BOMFILE, '\n' ))    
    close(conw) 
    }
}else{
    BOMFILE=paste0( getwd(), '/', basename (BOMFILE))
    cat(paste0('File:\n', BOMFILE, '\ndoes not appear UTF8 BOM.\n' ))   

}
close(conr)
于 2014-01-09T01:19:00.023 回答