web-dev-qa-db-ja.com

WindowsのR:文字エンコーディング地獄

OEM-866(キリル文字セット)としてエンコードされたCSVをWindowsのRにインポートしようとしています。 BOMなしのUTF-8に変換されたコピーも持っています。これらのファイルはどちらも、エンコーディングを指定すると、システム上の他のすべてのアプリケーションで読み取ることができます。

さらに、Linuxでは、Rは指定されたエンコーディングでこれらの特定のファイルを正常に読み取ることができます。 「fileEncoding」パラメーターを指定しない場合、WindowsでCSVを読み取ることもできますが、これによりテキストが判読できなくなります。 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
25
user27636

簡単な答え。

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を使用している場合は、ビューアーにキリル文字が表示され、コンソールにゴミが表示されます。たとえば、ランダムなキリル文字列を入力してEnterキーを押すと、ガベージ出力が表示されます。興味深いことに、Revolution Rには、アラビア語のテキストと同じ問題はありません。通常のRを使用している場合は、Sys.setlocale()で十分なようです。

'Sys.setlocale()'はユーザーG. Grothendieckによって提案されました: R、Windows and foreign language characters

5
user27636

現在のロケールでサポートされていない文字を含むファイルからデータを読み取るには、2つのオプションがあります。 @ user23676の提案に従ってロケールを変更するか、UTF-8に変換できます。 readrパッケージは、この変換を実行する_read.table_派生関数の代替を提供します。あなたはCP866ファイルを読むことができます

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

小さな問題が1つあります。つまり、_print.data.frame_にバグがあり、WindowsでUTF-8エンコードの列が正しく表示されないということです。 print.listof(oem.csv)またはprint(as.matrix(oem.csv))を使用してバグを回避できます。

これについては、ブログの投稿 http://people.fas.harvard.edu/~izahn/posts/reading-data-with-non-native-encoding-in-r/で詳しく説明しています。

5
Ista

FileEncodingをencodingに変更することで問題が解決する可能性があります。これらのパラメーターは、read関数では動作が異なります(?readを参照)。

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

しかし、念のために、いくつかの非自明の障害があるかもしれないので、より完全な答え。つまり、Windows(私の場合はWin 7)のRでキリル文字を使用することができます。

動作させるために、いくつかの可能なエンコーディングを試す必要があるかもしれません。テキストマイニングの重要な側面は、入力変数をデータに一致させることです。 Encoding()の関数は非常に便利です。iconv()も参照してください。したがって、ネイティブパラメータを確認することができます。

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

私の場合、エンコーディングはUTF-8ですが、これはシステム設定によって異なる場合があります。したがって、UTF-8とUTF-8-BOMで結果を試し、ラテン語の行とキリル文字の行を含むメモ帳++でテストファイルを作成できます。

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)とコンソールの両方で次のようになります。

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
puslet88

ここには素晴らしい答えがたくさんあり、重複もたくさんあると思います。私はうまくいけば、より完全な問題の説明と、上記の解決策を使用していた方法で貢献しようとしています。

私の状況-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 Environmentでの結果は次のとおりです。

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
2
vlad1490

Wikipedia によると:

バイトオーダーマーク(BOM)は、エンディアン(バイトオーダー)を通知するために使用されるUnicode文字です。[...] Unicode標準は、BOMをUTF-8で許可しますが、その使用を要求または推奨していません。

とにかく、Windowsの世界ではUTF8がBOMで使用されています。たとえば、標準のメモ帳エディタは、UTF-8として保存するときにBOMを使用します。

Linuxの世界で生まれた多くのアプリケーション(LaTexを含む、たとえば、inputencパッケージをutf8)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)
0
antonio