Wie schneide ich führende und nachfolgende Leerzeichen?

360

Ich habe einige Probleme mit führenden und nachfolgenden Leerzeichen in einem data.frame. ZB schaue ich mir gerne einen bestimmten rowin data.frameeinem bestimmten Zustand an:

> myDummy[myDummy$country == c("Austria"),c(1,2,3:7,19)] 

[1] codeHelper     country        dummyLI    dummyLMI       dummyUMI       
[6] dummyHInonOECD dummyHIOECD    dummyOECD      
<0 rows> (or 0-length row.names)

Ich habe mich gefragt, warum ich nicht die erwartete Leistung erhalten habe, da das Land Österreich offensichtlich in meinem Land existiert data.frame. Nachdem ich meinen Codeverlauf durchgesehen und versucht hatte herauszufinden, was schief gelaufen war, versuchte ich:

> myDummy[myDummy$country == c("Austria "),c(1,2,3:7,19)]
   codeHelper  country dummyLI dummyLMI dummyUMI dummyHInonOECD dummyHIOECD
18        AUT Austria        0        0        0              0           1
   dummyOECD
18         1

Alles, was ich im Befehl geändert habe, ist ein zusätzliches Leerzeichen nach Österreich.

Weitere störende Probleme treten offensichtlich auf. Zum Beispiel, wenn ich zwei Frames basierend auf der Länderspalte zusammenführen möchte. Einer data.frameverwendet, "Austria "während der andere Rahmen hat "Austria". Das Matching funktioniert nicht.

  1. Gibt es eine gute Möglichkeit, das Leerzeichen auf meinem Bildschirm anzuzeigen, damit ich mir des Problems bewusst werde?
  2. Und kann ich das führende und nachfolgende Leerzeichen in R entfernen?

Bisher habe ich ein einfaches PerlSkript geschrieben, das Leerzeichen entfernt, aber es wäre schön, wenn ich es irgendwie in R tun könnte.

Mropa
quelle
1
Ich habe gerade gesehen, dass sub()auch die PerlNotation verwendet wird. Das tut mir leid. Ich werde versuchen, die Funktion zu verwenden. Aber für meine erste Frage habe ich noch keine Lösung.
Mropa
4
Wie Hadley darauf hingewiesen hat, identifiziert dieser reguläre Ausdruck "^ \\ s + | \\ s + $" führende und nachfolgende Leerzeichen. so x <- gsub ("^ \\ s + | \\ s + $", "", x) viele von Rs Lesefunktionen haben diese Option: strip.white = FALSE
Jay

Antworten:

456

Der wahrscheinlich beste Weg ist, die nachfolgenden Leerzeichen zu verarbeiten, wenn Sie Ihre Datendatei lesen. Wenn Sie verwenden read.csvoder read.tableden Parameter einstellen können strip.white=TRUE.

Wenn Sie Zeichenfolgen anschließend bereinigen möchten, können Sie eine der folgenden Funktionen verwenden:

# returns string w/o leading whitespace
trim.leading <- function (x)  sub("^\\s+", "", x)

# returns string w/o trailing whitespace
trim.trailing <- function (x) sub("\\s+$", "", x)

# returns string w/o leading or trailing whitespace
trim <- function (x) gsub("^\\s+|\\s+$", "", x)

So verwenden Sie eine dieser Funktionen für myDummy$country:

 myDummy$country <- trim(myDummy$country)

Um das Leerzeichen anzuzeigen, können Sie Folgendes verwenden:

 paste(myDummy$country)

Hier werden die Zeichenfolgen angezeigt, die von Anführungszeichen (") umgeben sind, sodass Leerzeichen leichter zu erkennen sind.

f3lix
quelle
7
Wie Hadley darauf hingewiesen hat, identifiziert dieser reguläre Ausdruck "^ \\ s + | \\ s + $" führende und nachfolgende Leerzeichen. so x <- gsub ("^ \\ s + | \\ s + $", "", x) viele von Rs Lesefunktionen haben diese Option: strip.white = FALSE
Jay
50
Siehe auch str_trimim stringrPaket.
Richie Cotton
1
Plus eins für "Trimmfunktion jetzt für zukünftige Verwendung gespeichert" - danke!
Chris Beeley
4
Leider funktioniert strip.white = TRUE nur für Zeichenfolgen ohne Anführungszeichen.
Rodrigo
2
In R 3.2.0 gibt es eine viel einfachere Möglichkeit, Leerzeichen zu kürzen. Siehe die nächste Antwort!
Alex
519

Ab R 3.2.0 wurde eine neue Funktion zum Entfernen führender / nachfolgender Leerzeichen eingeführt:

trimws()

Siehe: http://stat.ethz.ch/R-manual/R-patched/library/base/html/trimws.html

wligtenberg
quelle
2
Dies hängt von der Definition der besten Antwort ab. Diese Antwort ist gut zu wissen (+1), aber in einem schnellen Test war sie nicht so schnell wie einige der Alternativen da draußen.
A5C1D2H2I1M1N2O1R2T1
scheint nicht für mehrzeilige Zeichenfolgen zu funktionieren, obwohl \nsie in der abgedeckten Zeichenklasse sind. trimws("SELECT\n blah\n FROM foo;")enthält noch Zeilenumbrüche.
Jubelt
6
@Jubbles Das ist das erwartete Verhalten. In der Zeichenfolge, die Sie an trimws übergeben, gibt es keine führenden oder nachfolgenden Leerzeichen. Wenn Sie führende und nachfolgende Leerzeichen aus jeder Zeile in der Zeichenfolge entfernen möchten, müssen Sie sie zuerst aufteilen. So: trimws (strsplit ("SELECT \ n blah \ n FROM foo;", "\ n") [[1]])
wligtenberg
1
Obwohl es sich um eine integrierte Funktion für neuere Versionen von R handelt, wird "nur" ein regulärer Ausdruck im PERL-Stil unter der Haube ausgeführt. Ich hätte vielleicht einen schnellen benutzerdefinierten C-Code erwartet, um dies zu tun. Vielleicht ist der trimwsRegex schnell genug. stringr::str_trim(basierend auf stringi) ist auch insofern interessant, als es eine völlig unabhängige internationalisierte String-Bibliothek verwendet. Sie würden denken, Whitespace wäre immun gegen Probleme mit der Internationalisierung, aber ich frage mich. Ich habe noch nie einen Vergleich der Ergebnisse von nativen und stringr/ stringioder Benchmarks gesehen.
Jack Wasey
Aus irgendeinem Grund konnte ich nicht herausfinden, trimws()entfernte meine führenden Leerzeichen nicht, während Bryans trim.strings()unten (nur 1 Stimme, meine!) ...
PatrickT
89

Verwenden Sie str_trim () im stringr-Paket, um den Leerraum zu bearbeiten. Das Paket hat ein Handbuch vom 15. Februar 2013 und ist in CRAN. Die Funktion kann auch Zeichenfolgenvektoren verarbeiten.

install.packages("stringr", dependencies=TRUE)
require(stringr)
example(str_trim)
d4$clean2<-str_trim(d4$V2)

(Gutschrift geht an Kommentator: R. Cotton)

userJT
quelle
2
Diese Lösung entfernte einige mutierte Leerzeichen, trimws()die nicht entfernt werden konnten.
Richard Telford
1
@ RichardTelford könnten Sie ein Beispiel geben? Denn das könnte als Fehler in trimws angesehen werden.
wligtenberg
IMO das ist die beste Lösung. Nicht viel Code und sehr performant
Peter
Vielen Dank für die Anforderung (stringr), dass ihre Dokumentation oder Beispiele diese erforderliche Codezeile nicht hatten!
pgee70
23

Eine einfache Funktion zum Entfernen von führenden und nachfolgenden Leerzeichen:

trim <- function( x ) {
  gsub("(^[[:space:]]+|[[:space:]]+$)", "", x)
}

Verwendungszweck:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"
Bernhard Kausler
quelle
11

ad1) Um Leerzeichen zu sehen, können Sie direkt print.data.framemit geänderten Argumenten aufrufen :

print(head(iris), quote=TRUE)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width  Species
# 1        "5.1"       "3.5"        "1.4"       "0.2" "setosa"
# 2        "4.9"       "3.0"        "1.4"       "0.2" "setosa"
# 3        "4.7"       "3.2"        "1.3"       "0.2" "setosa"
# 4        "4.6"       "3.1"        "1.5"       "0.2" "setosa"
# 5        "5.0"       "3.6"        "1.4"       "0.2" "setosa"
# 6        "5.4"       "3.9"        "1.7"       "0.4" "setosa"

Siehe auch ?print.data.framefür andere Optionen.

Marek
quelle
9

Verwenden Sie grep oder grepl, um Beobachtungen mit Leerzeichen zu finden, und sub, um sie zu entfernen.

names<-c("Ganga Din\t","Shyam Lal","Bulbul ")
grep("[[:space:]]+$",names)
[1] 1 3
grepl("[[:space:]]+$",names)
[1]  TRUE FALSE  TRUE
sub("[[:space:]]+$","",names)
[1] "Ganga Din" "Shyam Lal" "Bulbul"  
Jyotirmoy Bhattacharya
quelle
7
Oder etwas prägnanter"^\\s+|\\s+$"
Hadley
4
Ich wollte nur darauf hinweisen, dass man gsubstatt submit Hadleys Regexp verwenden muss. Damit subwird
nachfolgendes
Ich wusste nicht, dass Sie \ s usw. mit perl = FALSE verwenden können. Die Dokumente sagen, dass in diesem Fall die POSIX-Syntax verwendet wird, aber die akzeptierte Syntax ist tatsächlich eine Obermenge, die von der TRE-Regex-Bibliothek laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Bhattacharya
5

Ich würde es vorziehen, die Antwort als Kommentar zu user56 hinzuzufügen, kann sie jedoch nicht als unabhängige Antwort schreiben. Das Entfernen von führenden und nachfolgenden Leerzeichen kann auch durch die Funktion trim () aus dem gdata-Paket erreicht werden:

require(gdata)
example(trim)

Anwendungsbeispiel:

> trim("   Remove leading and trailing blanks    ")
[1] "Remove leading and trailing blanks"
KAA
quelle
5

Ein weiteres verwandtes Problem tritt auf, wenn zwischen den Eingaben mehrere Leerzeichen stehen:

> a <- "  a string         with lots   of starting, inter   mediate and trailing   whitespace     "

Sie können diese Zeichenfolge dann einfach in "echte" Token aufteilen, indem Sie einen regulären Ausdruck für das splitArgument verwenden:

> strsplit(a, split=" +")
[[1]]
 [1] ""           "a"          "string"     "with"       "lots"      
 [6] "of"         "starting,"  "inter"      "mediate"    "and"       
[11] "trailing"   "whitespace"

Beachten Sie, dass bei einer Übereinstimmung am Anfang einer (nicht leeren) Zeichenfolge das erste Element der Ausgabe "" "ist. Wenn jedoch am Ende der Zeichenfolge eine Übereinstimmung vorliegt, ist die Ausgabe dieselbe wie mit dem Streichholz entfernt.

TMOTTM
quelle
5

Eine andere Option ist die Verwendung der stri_trimFunktion aus dem stringiPaket, die standardmäßig führende und nachfolgende Leerzeichen entfernt:

> x <- c("  leading space","trailing space   ")
> stri_trim(x)
[1] "leading space"  "trailing space"

Verwenden Sie zum Entfernen nur führender Leerzeichen stri_trim_left. Verwenden Sie, um nur nachgestellte Leerzeichen zu entfernen stri_trim_right. Wenn Sie andere führende oder nachfolgende Zeichen entfernen möchten, müssen Sie dies mit angeben pattern =.

Siehe auch ?stri_trimfür weitere Informationen.

Jaap
quelle
2

Ich habe eine trim.strings ()Funktion zum Trimmen von führenden und / oder nachfolgenden Leerzeichen wie folgt erstellt:

# Arguments:    x - character vector
#            side - side(s) on which to remove whitespace 
#                   default : "both"
#                   possible values: c("both", "leading", "trailing")

trim.strings <- function(x, side = "both") { 
    if (is.na(match(side, c("both", "leading", "trailing")))) { 
      side <- "both" 
      } 
    if (side == "leading") { 
      sub("^\\s+", "", x)
      } else {
        if (side == "trailing") {
          sub("\\s+$", "", x)
    } else gsub("^\\s+|\\s+$", "", x)
    } 
} 

Zur Veranschaulichung:

a <- c("   ABC123 456    ", " ABC123DEF          ")

# returns string without leading and trailing whitespace
trim.strings(a)
# [1] "ABC123 456" "ABC123DEF" 

# returns string without leading whitespace
trim.strings(a, side = "leading")
# [1] "ABC123 456    "      "ABC123DEF          "

# returns string without trailing whitespace
trim.strings(a, side = "trailing")
# [1] "   ABC123 456" " ABC123DEF"   
Bryan
quelle
1

Beste Methode ist trimws ()

Der folgende Code wendet diese Funktion auf den gesamten Datenrahmen an

mydataframe <- data.frame (lapply (mydataframe, trimws), stringsAsFactors = FALSE)

Santosh Kadge
quelle
oder df[] <- lapply(df, trimws)kompakter sein. In beiden Fällen werden Spalten jedoch zum Zeichen gezwungen. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)sicher sein.
Moody_Mudskipper
1

Ich habe versucht, trim (). Funktioniert gut mit Leerzeichen sowie dem '\ n'. x = '\ n Harden, J. \ n'

trimmen (x)

J. Dan
quelle
0
myDummy[myDummy$country == "Austria "] <- "Austria"

Danach müssen Sie R zwingen, "Österreich" nicht als Level zu erkennen. Stellen wir uns vor, Sie haben auch "USA" und "Spanien" als Level:

myDummy$country = factor(myDummy$country, levels=c("Austria", "USA", "Spain"))

Ein bisschen weniger einschüchternd als die Antwort mit der höchsten Stimme, aber es sollte trotzdem funktionieren.

David Mitchell
quelle