Windows上的R:字符编码地狱

问题描述 投票:19回答:5

我正在尝试将编码为OEM-866(西里尔语字符集)的CSV导入到Windows上的R中。我还有一份已经转换为UTF-8无副BOM的副本。一旦指定了编码,这两个文件都可以被我的系统上的所有其他应用程序读取。

此外,在Linux上,R可以使用指定的编码读取这些特定文件。我也可以在Windows上读取CSV如果我没有指定“fileEncoding”参数,但这会导致文本不可读。当我在Windows上指定文件编码时,对于OEM和Unicode文件,我总是会收到以下错误:

原始OEM文件导入:

> 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

没有BOM文件导入的UTF-8:

> 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

本地信息:

> 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"

Windows上的R对此负责的是什么?除了放弃窗户之外,我已经尝试了所有我能做到的事情。

谢谢

(其他尝试失败):

>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
r csv encoding utf-8 non-ascii-characters
5个回答
5
投票

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

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

但是,如果有更完整的答案,因为可能存在一些非明显的障碍。简而言之:可以在Windows上使用Cyrillic in R(在我的案例中是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
Минемум конкыптам, тхэопхражтуз, ед про

这可以导入到R中

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")

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

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

但更重要的是,脚本无法访问它。

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

No BOM UTF-8的结果对于view(raw_table1)和console都是这样的。

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你提到的警告仍然没有明显的重要影响。


5
投票

简单回答。

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 - 您将在Viewer中看到西里尔文本并在控制台中看到垃圾。因此,例如,如果您键入随机的西里尔字符串并按Enter键,您将获得垃圾输出。有趣的是,Revolution R与阿拉伯语文本没有相同的问题。如果你使用常规R,似乎Sys.setlocale()就足够了。

'Sys.setlocale()'由用户G. Grothendieck在这里提出:R, Windows and foreign language characters


4
投票

从包含当前语言环境不支持的字符的文件中读取数据有两种选择。您可以按@ 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/的博客文章中更详细地讨论过这个问题


2
投票

我认为这里有很多很棒的答案,还有很多重复的答案。我尝试用希望更完整的问题描述和我使用上述解决方案的方式做出贡献。

我的情况 - 将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看到的结果是这样的:

result of translation as seen in the R Environment

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

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

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

result of translation as seen in the R Environment

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

我决定实际使用这样的函数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环境的结果是:

properly visualized translation in R Environment

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

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

properly visualised and written file as seen from Notepad++

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

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

0
投票

Wikipedia说:

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

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

Linux世界中出现的许多应用程序(包括LaTex,例如使用带有inputencutf8软件包)在读取BOM-UTF-8文件时出现问题。

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)
© www.soinside.com 2019 - 2024. All rights reserved.