web-dev-qa-db-fra.com

R sur Windows: l'enfer de l'encodage des caractères

J'essaie d'importer un fichier CSV encodé en tant que OEM-866 (jeu de caractères cyrillique) dans R sous Windows. J'ai aussi une copie qui a été convertie en UTF-8 sans nomenclature. Ces deux fichiers sont lisibles par toutes les autres applications de mon système, une fois le codage spécifié.

De plus, sous Linux, R peut très bien lire ces fichiers avec les codages spécifiés. Je peux également lire le fichier CSV sous Windows SI je ne spécifie pas le paramètre "fileEncoding", mais cela entraîne un texte illisible. Lorsque je spécifie le codage de fichier sous Windows, les erreurs suivantes apparaissent toujours, à la fois pour le fichier OEM et le fichier Unicode:

Importation du fichier OEM d'origine:

> 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 sans importation de fichier BOM:

> 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

Informations locales:

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

Qu'est-ce qui fait que R sur Windows est responsable de cela? J'ai à peu près tout essayé à ce stade, à part l'amerrissage des fenêtres.

Je vous remercie

(Autres tentatives infructueuses):

>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
19
user27636

Réponse simple. 

Sys.setlocale(locale = "Russian")

si vous voulez juste la langue russe (pas les formats, ni la monnaie):

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

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

Si vous utilisez Revolution R Open 3.2.2 par la suite, vous devrez peut-être également définir les paramètres régionaux dans le Panneau de configuration: sinon, si vous avez RStudio, vous verrez du texte en cyrillique dans le visualiseur et des résidus dans la console. Ainsi, par exemple, si vous tapez une chaîne cyrillique aléatoire et que vous appuyez sur Entrée, vous obtiendrez une sortie de mémoire. Fait intéressant, Revolution R n’a pas le même problème avec le texte arabe. Si vous utilisez un R normal, il semble que Sys.setlocale() est suffisant.

'Sys.setlocale ()' a été suggéré par l'utilisateur G. Grothendieck ici: R, Windows et caractères en langues étrangères

5
user27636

Il est possible que votre problème soit résolu en changeant fileEncoding en encodage, ces paramètres fonctionnent différemment dans la fonction de lecture (voir? Lire).

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

Juste au cas où, cependant, une réponse plus complète, car il pourrait y avoir des obstacles non évidents. En bref: il est possible de travailler avec cyrillique sous R sous Windows (dans mon cas, Win 7). 

Vous devrez peut-être essayer quelques encodages possibles pour que les choses fonctionnent. Pour l'exploration de texte, un aspect important consiste à faire en sorte que vos variables d'entrée correspondent aux données. La fonction Encoding () y est très utile, voir aussi iconv (). Ainsi, il est possible de voir votre paramètre natif.

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

Dans mon cas, le codage est UTF-8, bien que cela puisse dépendre des paramètres du système. Nous pouvons donc essayer le résultat avec UTF-8 et UTF-8-BOM et créer un fichier de test dans le bloc-notes ++ avec une ligne en latin et une ligne en cyrillique.

UTF8_nobom_cyrillic.csv et UTF8_bom_cyrillic.csv

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

Ceci peut être importé dans R par 

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

Les résultats obtenus sont pour moi pour le cyrillique normal dans la vue (raw_table1) et pour le charabia dans la console.

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

Plus important encore, le script ne permet pas d'y accéder.

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

Les résultats pour No BOM UTF-8 ressemblent à peu près à ceux de view (raw_table1) et de la 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>

Cependant, il est important de noter qu'une recherche du mot à l'intérieur donnera le résultat correct.

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

Ainsi, il est possible de travailler avec des caractères non standard dans Windows, en fonction de vos objectifs précis. Je travaille régulièrement avec des caractères latins non anglais et l'UTF-8 permet de travailler dans Windows 7 sans problème. "WINDOWS-1252" s'est avéré utile pour exporter vers des lecteurs Microsoft tels qu'Excel.

PS Les mots russes ont été générés ici http://generator.lorem-ipsum.info/_russian , donc essentiellement dépourvu de sens.

5
puslet88

Il existe deux options pour lire les données à partir de fichiers contenant des caractères non pris en charge par les paramètres régionaux actuels. Vous pouvez modifier vos paramètres régionaux comme suggéré par @ user23676 ou vous pouvez convertir en UTF-8. Le package readr fournit des remplacements pour les fonctions dérivées read.table qui effectuent cette conversion pour vous. Vous pouvez lire le fichier CP866 avec

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

Il y a un petit problème, à savoir qu'il existe un bogue dans print.data.frame qui entraîne l'affichage incorrect des colonnes avec le codage UTF-8 sous Windows. Vous pouvez contourner le bogue avec print.listof(oem.csv) ou print(as.matrix(oem.csv)).

J'ai discuté de cela plus en détail dans un article de blog sur http://people.fas.harvard.edu/~izahn/posts/reading-data-with-non-native-encoding-in-r/

3
Ista

Je pense qu'il y a toutes d'excellentes réponses ici et beaucoup de doublons. J'essaie de contribuer avec une description plus complète du problème, espérons-le, et de la manière dont j'utilisais les solutions ci-dessus.

Ma situation - Écriture des résultats de l'API Google Translate dans le fichier sous R

Dans mon cas particulier, j’envoyais du texte à 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")

Le résultat que je vois dans le R Environment est comme ceci: 

 result of translation as seen in the R Environment

Cependant, si j'imprime ma variable dans la console, je verrai ce texte joliment formaté (j'espère):

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

Dans ma situation, je devais écrire un fichier dans Computer File System à l'aide de la fonction R write.table()...

 result of translation as seen in the R Environment

Ma solution - tiré des réponses ci-dessus:

J'ai décidé d'utiliser réellement la fonction Sys.setlocale() comme ceci:

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"

Après cela, ma traduction a été correctement visualisée dans l'environnement 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")

Le résultat dans R Environment était:

 properly visualized translation in R Environment

Après cela, je pourrais écrire mon fichier et enfin voir le texte chinois:

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

 properly visualised and written file as seen from Notepad++

Enfin, dans ma fonction de traduction, je reviendrais à mes paramètres d'origine avec:

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"

Ma conclusion:

Avant de traiter avec des langues spécifiques dans R:

  1. Configurez les paramètres régionaux sur ceux de la langue Sys.setlocale(locale = "Chinese") # set locale to Chinese
  2. Effectuer toutes les manipulations de données
  3. Retournez à vos paramètres d'origine Sys.setlocale() # set original system settings
2
vlad1490

Selon Wikipedia :

La marque d'ordre d'octet (BOM) est un caractère Unicode utilisé pour signaler la finalité (ordre d'octet) [...] La norme Unicode autorise la nomenclature dans UTF-8, mais n'exige ni ne recommande son utilisation.

Quoi qu'il en soit, dans le monde Windows, UTF8 est utilisé avec BOM. Par exemple, l'éditeur de bloc-notes standard utilise la nomenclature lors de l'enregistrement au format UTF-8. 

De nombreuses applications nées dans un monde Linux (y compris LaTex, par exemple lors de l'utilisation du package inputenc avec le utf8) posent des problèmes lors de la lecture de fichiers BOM-UTF-8. 

Notepad ++ est une option typique permettant de convertir des types de codage, des fins de ligne Linux/DOS/Mac et la suppression de la nomenclature. 

Comme nous le savons, la représentation non recommandée de la nomenclature par la UTF-8 est la séquence d'octets 

0xEF,0xBB,0xBF

au début du flux de texte, pourquoi ne pas l'enlever avec R lui-même? 

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