2017-09-10 1 views
3

Ich bin verwirrt darüber, warum bestimmte Zeichen (zB "Ě", "Č" und "ŝ") ihre diakritischen Zeichen in einem Datenrahmen verlieren, während andere (zB "Š" und "š") nicht. Mein Betriebssystem ist übrigens Windows 10. In meinem Beispielcode unten hat ein Vektor czechvec 11 Einzelzeichenfolgen, alle slawischen Akzentbuchstaben. R zeigt diese Zeichen richtig an. Dann wird ein Datenrahmen mydf mit czechvec als zweite Spalte erstellt (die Funktion I() wird verwendet, damit sie nicht in einen Faktor umgewandelt wird). Aber wenn R mydf oder eine Zeile von mydf anzeigt, konvertiert es die meisten dieser Zeichen in ihr normales Ascii-Äquivalent; z.B. mydf [3,] zeigt den Charakter als "E" nicht "Ě". Aber Subskribierung mit Zeile und Spalte, z. mydf [3,2], es zeigt richtig das akzentuierte Zeichen ("Ě"). Warum sollte es einen Unterschied machen, ob R die ganze Zeile oder nur eine Zelle anzeigt? Und warum sind einige Zeichen wie "Š" völlig unbeeinflusst? Auch wenn ich diesen Datenrahmen in eine Datei schreibe, verliert er vollständig den Akzent, obwohl ich fileEncoding = "UTF-8" angegeben habe.R: akzentuierte Zeichen im Datenrahmen

> charvals <- c(193, 269, 282, 268, 262, 263, 348, 349, 350, 352, 353) 
> hexvals <- as.hexmode(charvals) 
> czechvec <- unlist(strsplit(intToUtf8(charvals), "")) 
> czechvec 
[1] "Á" "č" "Ě" "Č" "Ć" "ć" "Ŝ" "ŝ" "Ş" "Š" "š" 
> 
> mydf = data.frame(dec=charvals, char=I(czechvec), hex=I(format(hexvals, width=4, upper.case=TRUE))) 
> mydf 
    dec char hex 
1 193 Á 00C1 
2 269 c 010D 
3 282 E 011A 
4 268 C 010C 
5 262 C 0106 
6 263 c 0107 
7 348 S 015C 
8 349 s 015D 
9 350 S 015E 
10 352 Š 0160 
11 353 š 0161 
> mydf[3,2] 
[1] "Ě" 
> mydf[3,] 
    dec char hex 
3 282 E 011A 
> 
> write.table(mydf, file="myfile.txt", fileEncoding="UTF-8") 
> 
> df2 <- read.table("myfile.txt", stringsAsFactors=FALSE, fileEncoding="UTF-8") 
> df2[3,2] 
[1] "E" 

Bearbeitet hinzuzufügen: Per Ernest A ist dieses Verhalten in Linux nicht reproduzierbar. Es muss ein Windows-Problem sein. (Ich verwende R 3.4.1 für Windows.)

Antwort

1

Ich kann dieses Verhalten nicht reproduzieren, R Version 3.3.3 (Linux) verwenden.

> data.frame(dec=charvals, char=I(czechvec), hex=I(format(hexvals, width=4, upper.case=TRUE))) 
    dec char hex 
1 193 Á 00C1 
2 269 č 010D 
3 282 Ě 011A 
4 268 Č 010C 
5 262 Ć 0106 
6 263 ć 0107 
7 348 Ŝ 015C 
8 349 ŝ 015D 
9 350 Ş 015E 
10 352 Š 0160 
11 353 š 0161 
0

Dank Ernest A Antwort überprüfen, ob das seltsame Verhalten, das ich beobachtet tritt nicht in Linux, ich R WINDOWS UTF-8 BUG gegoogelt, die zu diesem Artikel von Ista Zahn führte mich: Escaping from character encoding hell in R on Windows

Der Artikel bestätigt gibt es einen Bug in der data.frame-Druckmethode unter Windows und gibt einige Problemumgehungen. (Der Artikel notiert jedoch nicht das Problem mit write.table in Windows für Datenrahmen mit fremdsprachigem Text.)

Eine von Zahn vorgeschlagene Problemumgehung ist, das Gebietsschema an die Sprache anzupassen, mit der wir arbeiten:

Sys.setlocale(category = "LC_CTYPE", locale = "czech") 
charvals <- c(193, 269, 282, 268, 262, 263, 348, 349, 350, 352, 353) 
hexvals <- format(as.hexmode(charvals), width=4, upper.case=TRUE) 
df1  <- data.frame(dec=charvals, char=I(unlist(strsplit(intToUtf8(charvals), ""))), hex=I(hexvals)) 

print.listof(df1) 

dec : 
[1] 193 269 282 268 262 263 348 349 350 352 353 

char : 
[1] "Á" "č" "Ě" "Č" "Ć" "ć" "Ŝ" "ŝ" "Ş" "Š" "š" 

hex : 
[1] "00C1" "010D" "011A" "010C" "0106" "0107" "015C" "015D" "015E" "0160" 
[11] "0161" 

df1 
    dec char hex 
1 193 Á 00C1 
2 269 č 010D 
3 282 Ě 011A 
4 268 Č 010C 
5 262 Ć 0106 
6 263 ć 0107 
7 348 S 015C 
8 349 s 015D 
9 350 Ş 015E 
10 352 Š 0160 
11 353 š 0161 

Beachten Sie, dass die tschechischen Zeichen nun korrekt angezeigt werden, aber nicht „S“ und „S“, Unicode U + 015C und U + 015D, die offenbar in Esperanto verwendet werden. Aber mit dem Befehl print.listof werden alle Zeichen korrekt angezeigt. (By the way, dput(df1) listet die Esperanto Zeichen falsch, als "S" und "s".)

write.table(df1, file="special characters example.txt", fileEncoding="UTF-8") 
df2 <- read.table("special characters example.txt", stringsAsFactors=FALSE, fileEncoding="UTF-8") 

print.listof(df2) 
dec : 
[1] 193 269 282 268 262 263 348 349 350 352 353 

char : 
[1] "Á" "č" "Ě" "Č" "Ć" "ć" "S" "s" "Ş" "Š" "š" 

hex : 
[1] "00C1" "010D" "011A" "010C" "0106" "0107" "015C" "015D" "015E" "0160" 
[11] "0161" 

Als ich write.table DF1 und dann read.table es zurück als DF2, das "S" und "S" Zeichen haben ihren circumflex verloren. Dies muss ein Problem mit dem write.table Befehl sein, wie bestätigt, wenn ich die Datei mit einer anderen Anwendung wie OpenOffice Writer öffne. Die tschechischen Zeichen sind alle korrekt, aber "Ŝ" und "ŝ" wurden in "S" und "s" geändert.

Die beste Problemumgehung für meine Zwecke ist, anstatt das eigentliche Zeichen in meinen Datenrahmen zu setzen, den Unicode-Wert aufzuzeichnen, dann write.table zu verwenden und die UNICHAR-Funktion in OpenOffice Calc zu verwenden das Zeichen selbst in die Datei. Aber das ist unbequem.

Ich glaube, der gleiche Fehler auf diese Frage relevant ist: how to read data in utf-8 format in R?

Edited hinzufügen: Andere ähnliche Fragen, die ich jetzt auf Stack-Überlauf gefunden habe:

Why do some Unicode characters display in matrices, but not data frames in R?

UTF-8 file output in R

Write UTF-8 files from R

Und ich fand eine Abhilfe für die Problem mit der Anzeige von Peter Meissner hier:

http://r.789695.n4.nabble.com/Unicode-display-problem-with-data-frames-under-Windows-tp4707639p4707667.html

Es geht um Ihre eigene Klasse unicode_df und Druckfunktion print.unicode_df definieren.

Dies löst immer noch nicht das Problem, das ich mit write.table habe, um meinen Datenrahmen (der einige Spalten mit Text in verschiedenen europäischen Sprachen enthält) in eine Datei zu schreiben, die in eine Tabelle oder eine beliebige Anwendung importiert werden kann. Aber vielleicht kann die Lösung von Meissner angepasst werden, um mit write.table zu arbeiten.

0

Hier ist eine Funktion, die write.unicode.csv paste und writeLines (mit useBytes=TRUE) verwendet eine Datenrahmen fremdsprachige Zeichen enthält, zu exportieren (codiert in UTF-8) in eine CSV-Datei. Alle Zellen im Datenrahmen werden in Anführungszeichen in der CSV-Datei eingeschlossen.

#function that will create a CSV file for a data frame containing Unicode text 
#this can be used instead of write.csv in R for Windows 
#source: https://stackoverflow.com/questions/46137078/r-accented-characters-in-data-frame 
#this is not elegant, and probably not robust 

write.unicode.csv <- function(mydf, filename="") { #mydf can be a data frame or a matrix 
    linestowrite <- character(length = 1+nrow(mydf)) 
    linestowrite[1] <- paste('"","', paste(colnames(mydf), collapse='","'), '"', sep="") #first line will have the column names 
    if(nrow(mydf)<1 | ncol(mydf)<1) print("This is not going to work.")  #a bit of error checking 
    for(k1 in 1:nrow(mydf)) { 
    r <- paste('"', k1, '"', sep="") #each row will begin with the row number in quotes 
    for(k2 in 1:ncol(mydf)) {r <- paste(r, paste('"', mydf[k1, k2], '"', sep=""), sep=",")} 
    linestowrite[1+k1] <- r 
    } 
    writeLines(linestowrite, con=filename, useBytes=TRUE) 
    } #end of function 

Sys.setlocale(category = "LC_CTYPE", locale = "usa") 
charvals <- c(193, 269, 282, 268, 262, 263, 348, 349, 350, 352, 353) 
hexvals <- format(as.hexmode(charvals), width=4, upper.case=TRUE) 
df1  <- data.frame(dec=charvals, char=I(unlist(strsplit(intToUtf8(charvals), ""))), hex=I(hexvals)) 

print.listof(df1) 

write.csv(df1, file="test1.csv") 
write.csv(df1, file="test2.csv", fileEncoding="UTF-8") 
write.unicode.csv(df1, filename="test3.csv") 

dftest1 <- read.csv(file="test1.csv", encoding="UTF-8", colClasses="character") 
dftest2 <- read.csv(file="test2.csv", encoding="UTF-8", colClasses="character") 
dftest3 <- read.csv(file="test3.csv", encoding="UTF-8", colClasses="character") 

print("CSV file written using write.csv with no fileEncoding parameter:") 
print.listof(dftest1) 

print('CSV file written using write.csv with fileEncoding="UTF-8":') 
print.listof(dftest2) 

print("CSV file written using write.unicode.csv:") 
print.listof(dftest3) 
Verwandte Themen