2015-11-02 5 views
5

Es ist dieses seltsame Verhalten von stringr, die mich wirklich nervt. stringr ändert ohne Warnung die Codierung einiger Zeichenfolgen, die exotische Zeichen enthalten, in meinem Fall ø, å, æ, é und einige andere ... Wenn Sie str_trim einen Vektor von Zeichen, dann werden diejenigen mit exotischen Buchstaben in ein neues umgewandelt Codierung.Warum verändert Stringr die Kodierung beim Manipulieren von Strings?

letter1 <- readline('Gimme an ASCII character!')  # try q or a 
letter2 <- readline('Gimme an non-ASCII character!') # try ø or é 
Letters <- c(letter1, letter2) 
Encoding(Letters)   # 'unknown' 
Encoding(str_trim(Letters)) # mixed 'unknown' and 'UTF-8' 

Dies ist ein Problem, weil ich data.table für (fast) merge von großen Tabellen verwenden und dass data.table nicht gemischte Codierung unterstützt und weil ich nicht einen Weg, um wieder auf die einheitliche Codierung finden konnte, .

Alle Probleme?

EDIT: Ich dachte, ich könnte zurück zu den Basisfunktionen, aber sie schützen nicht entweder Codierung. paste konserviert es, aber nicht sub zum Beispiel.

Encoding(paste(' ', Letters))     # 'unknown' 
Encoding(str_c(' ', Letters))     # mixed 
Encoding(sub('^ +', '', paste(' ', Letters))) # mixed 
+0

Ich sehe es auch gemischt für 'Buchstaben'. By the way, 'Buchstaben' ist eine konstante Zeichenfolge in der Basis R. – Frank

+0

'unbekannt' ist die lokale Codierung, wenn ich es richtig verstanden habe, so kann es auf die Maschinen abhängen, denke ich ... Ich habe Briefe für Briefe geändert, seit Sie schienen verärgert, ich überschreibe eine Konstante. – Arthur

+0

Wenn Sie eine Möglichkeit haben, eine "unbekannte" Kodierung auf einer beliebigen Maschine zu erstellen, teilen Sie diese bitte mit! – Arthur

Antwort

1

R macht es nicht immer einfach, zwischen Codierungen zu konvertieren (es gibt die Funktion iconv dafür, aber was diese Funktion akzeptiert, ist plattformabhängig). Doch zumindest können Sie immer die Codierung zurückgesetzt Markierung einer Zeichenfolge „unbekannt“:

Letters = str_trim(Letters) 
Encoding(Letters) 
# [1] "unknown" "UTF-8" 
Encoding(Letters) = '' 
Encoding(Letters) 
# [1] "unknown" "unknown" 

Beachten Sie jedoch, dass dies nur Marken die Codierung einer Zeichenkette, ist es nicht wirklich re- kodiere die Zeichenkette. Als Konsequenz kann dies zu verzerrten Daten führen. Wie in den Kommentaren erwähnt, ist dies im besten Fall ein Hack, keine eigentliche Lösung für das Problem.

Encoding veranschaulicht R Probleme mit Codierungen ordnungsgemäß zu arbeiten. Die Dokumentation lautet:

ASCII-Zeichenfolgen werden nie mit einer deklarierten Codierung markiert, da ihre Darstellung in allen unterstützten Codierungen identisch ist.

... die gar offensichtlich nicht hilfreich (und auch mehr als nur ein wenig irreführend, eine UTF-8-String nur aus Codepunkten < 128 kann in eine ASCII-Zeichenfolge nicht zu unterscheiden aussehen, aber auf sie betrieben werden, sollten zu unterschiedlichen Ergebnissen führen abhängig von der Codierung, weshalb es sollte effektiv markiert werden).

Interessanterweise weder enc2native noch enc2utf8 wird hier die gewünschte Sache tun - sowohl in verschiedenen Codierungen für die beiden Strings in Letters ergeben wird, eine direkte Folge des Encoding Problems wie oben zitiert.

+1

Der in dieser Antwort vorgeschlagene Ansatz ist nicht gut. Zum einen funktioniert das unter Windows überhaupt nicht (oder möglicherweise auf einer Plattform, auf der die Standardcodierung nicht UTF8 ist). Zum anderen unterscheidet es nicht eindeutig zwischen _Verändern der Kodierung (z. B. mit "iconv") und _markieren_ der Kodierung (mit "Kodierung"). Allgemeiner existiert das Problem, das es zu lösen versucht, tatsächlich nicht; Die Strings, die von 'str_trim' und anderen Funktionen im stringr-Paket zurückgegeben werden, sind vollkommen in Ordnung, und die Elemente _ haben keine unterschiedlichen Codierungen_. Wie dokumentiert, markiert 'Encoding' keine ASCII-Zeichen. – Ista

+0

@Ista Sie sagen, dass die verschiedenen Kodierungen kein Problem darstellen, aber wenn Sie die Frage betrachten, ist das einfach nicht wahr. Außerdem markiere ich absichtlich nur die Kodierung und konvertiere nicht, da, wie Sie bemerkt haben, die Kodierungskonvertierung in R nicht auf allen Plattformen in gleichem Maße unterstützt wird.Jetzt stimme ich Ihnen vollkommen zu, dass dies keine richtige Lösung ist, weshalb ich genau das als Inhalt und nicht als Antwort gepostet habe, bis das OP mich auch gebeten hat, eine Antwort zu posten. –

+0

Es gibt keine unterschiedlichen Codierungen. Alle Elemente des von 'str_trim' zurückgegebenen Zeichenvektors sind in UTF-8 kodiert. Versuchen Sie, diese Antwort unter Windows auszuführen (drucken Sie anschließend Buchstaben), und Sie werden sehen, warum das Entfernen des Kodierungsmarkers eine schlechte Idee ist. Versuchen Sie tatsächlich, einige "data.table" -Objekte auf UTF-8-codierten Strings zusammenzufassen (ohne die 'Encoding' zu entfernen) und Sie werden sehen, dass es korrekt funktioniert, genau wie es in der Warnmeldung heißt. Ich weiß, warum du diese Antwort gepostet hast, aber um anderen zu helfen, die in Zukunft auf diese Frage stoßen, bitte bearbeite sie, um klarzustellen, dass dies um Ärger geht. – Ista

3

stringr wird Ändern der Codierung, da stringr ein Wrapper um das Paket stringi ist, und stringi kodiert immer in UTF-8. Details und eine Erläuterung dieser Design-Option finden Sie unter help("stringi-encoding", package = "stringi").

Um Probleme beim Zusammenführen von data.table s zu vermeiden, stellen Sie sicher, dass alle id Variablen in UTF-8 codiert sind. Sie können dies unter Verwendung von stri_enc_toutf8 im -Paket oder unter Verwendung von iconv tun.

+0

mit 'iconv' gibt offenbar gemischt enconding:' Encoding (iconv (Buchstaben, to = 'UTF-8')) '; 'stri_enc_toutf8' gibt überraschend einen einheitlich nativ codierten Vektor ...:' Encoding (stringi ::: stri_enc_toutf8 (Letters)) '; Was ich nicht verstehe ist warum ** Mixed ** Encoding? – Arthur

+0

Es ist wahrscheinlich nicht wirklich gemischt, das ist nur eine Eigenart der "Encoding" -Funktion. Insbesondere werden ASCII-Zeichen niemals mit einer Kodierung versehen, siehe 'Kodierung' für Details. – Ista

+0

Vielen Dank für die Erklärung. Aber wenn Mixed-Encoding nur der Standard ist, warum beschwert sich 'data.table'? Und warum geht es so schlecht damit um? Außer einigen hundert Millionen Anglophonen verwenden alle anderen Nicht-ASCII-Zeichen. Ich meine: die unerwünschte Folge der Verwendung von 'Stringr'-Funktionen ist, dass ich UTF-8 für Nicht-ASCII-Zeichen bekomme; aber ich bekomme ** falsche Ergebnisse in 'data.frame', wenn ich diese zusammenfasse. – Arthur

2

Mit this recent commit kümmert sich data.table jetzt implizit um diese gemischten Codierungen, indem beim Erstellen von Daten korrekte Codierungen sichergestellt werden.Tabellen, sowie durch die Sicherstellung der richtigen Kodierungen in Funktionen wie unique() und duplicated().

Siehe Nachricht (23) unter Bugs für v1.9.7 in README.md.

Bitte testen Sie und schreiben Sie zurück, wenn Sie weitere Probleme haben.

Verwandte Themen