Jak przyciąć wiodące i końcowe białe znaki?

360

Mam pewne problemy z prowadzeniem i kończeniem białych znaków w ramce data.frame. Np. Lubię przyjrzeć się konkretnemu roww data.frameoparciu o pewien warunek:

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

Zastanawiałem się, dlaczego nie uzyskałem oczekiwanej produkcji, skoro Austria oczywiście istniała w moim kraju data.frame. Po przejrzeniu historii kodu i próbie ustalenia, co poszło nie tak, próbowałem:

> 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

Wszystko, co zmieniłem w poleceniu, to dodatkowe białe znaki po Austrii.

Oczywiście powstają dalsze irytujące problemy. Np. Kiedy chcę scalić dwie ramki na podstawie kolumny kraju. Jedna data.frameużywa, "Austria "a druga ma "Austria". Dopasowywanie nie działa.

  1. Czy istnieje dobry sposób na „pokazanie” białych znaków na ekranie, aby zdawać sobie sprawę z problemu?
  2. Czy mogę usunąć wiodące i końcowe białe znaki w R?

Do tej pory pisałem prosty Perlskrypt, który usuwa białe spacje, ale byłoby miło, gdybym mógł jakoś to zrobić wewnątrz R.

mropa
źródło
1
Właśnie widziałem, że sub()używa również Perlnotacji. Przepraszam za to. Spróbuję użyć tej funkcji. Ale na moje pierwsze pytanie nie mam jeszcze rozwiązania.
mropa
4
Jak wcześniej wskazał to wyrażenie regularne „^ \\ s + | \\ s + $” zidentyfikuje początkowe i końcowe białe znaki. więc x <- gsub ("^ \\ s + | \\ s + $", "", x) wiele funkcji odczytu R ma taką opcję: strip.white = FALSE
Jay

Odpowiedzi:

456

Prawdopodobnie najlepszym sposobem jest obsługa końcowych białych znaków podczas odczytywania pliku danych. Jeśli używasz read.csvlub read.tablemożesz ustawić parametr strip.white=TRUE.

Jeśli chcesz później wyczyścić ciągi, możesz użyć jednej z następujących funkcji:

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

Aby użyć jednej z tych funkcji w myDummy$country:

 myDummy$country <- trim(myDummy$country)

Aby „pokazać” białe znaki, których możesz użyć:

 paste(myDummy$country)

który pokaże ciągi otoczone znakami cudzysłowu („), dzięki czemu łatwiej będzie dostrzec białe spacje.

f3lix
źródło
7
Jak wcześniej wskazał to wyrażenie regularne „^ \\ s + | \\ s + $” zidentyfikuje początkowe i końcowe białe znaki. więc x <- gsub ("^ \\ s + | \\ s + $", "", x) wiele funkcji odczytu R ma taką opcję: strip.white = FALSE
Jay
50
Zobacz także str_trimw stringrpakiecie.
Richie Cotton
1
Plus jeden za „Funkcja przycinania jest teraz zapisana do użytku w przyszłości” - dzięki!
Chris Beeley,
4
Niestety, strip.white = TRUE działa tylko na ciągach niecytowanych.
Rodrigo,
2
Jest dużo łatwiejszy sposób przycinania białych znaków w R 3.2.0. Zobacz następną odpowiedź!
Alex
519

Począwszy od wersji 3.2.0 wprowadzono nową funkcję usuwania wiodących / końcowych białych znaków:

trimws()

Zobacz: http://stat.ethz.ch/R-manual/R-pched/library/base/html/trimws.html

Wligtenberg
źródło
2
To zależy od definicji najlepszej odpowiedzi. Ta odpowiedź jest miła (+1), ale w szybkim teście nie była tak szybka, jak niektóre z dostępnych tam alternatyw.
A5C1D2H2I1M1N2O1R2T1
wydaje się nie działać dla ciągów wieloliniowych, mimo \nże należy do klasy znaków objętych. trimws("SELECT\n blah\n FROM foo;")wciąż zawiera nowe linie.
Jubbles,
6
@Jubbles Takie jest oczekiwane zachowanie. W ciągu przekazywanym do trimws nie ma żadnych początkowych ani końcowych białych znaków. Jeśli chcesz usunąć początkowe i końcowe białe spacje z każdej linii w łańcuchu, najpierw musisz go podzielić. W ten sposób: trimws (strsplit („SELECT \ n blah \ n Foo;”, „\ n”) [[1]])
wligtenberg
1
Chociaż wbudowana funkcja dla najnowszych wersji R, „po prostu” wykonuje wyrażenie regularne w stylu PERL pod maską. Być może spodziewałem się szybkiego szybkiego niestandardowego kodu C. Może trimwsregex jest wystarczająco szybki. stringr::str_trim(oparty na stringi) jest również interesujący, ponieważ wykorzystuje całkowicie niezależną międzynarodową bibliotekę ciągów. Można by pomyśleć, że białe znaki będą odporne na problemy z internacjonalizacją, ale zastanawiam się. Nigdy nie widziałem porównania wyników natywnych vs stringr/ stringilub jakichkolwiek testów porównawczych.
Jack Wasey,
Z jakiegoś powodu nie mogłem się domyślić, trimws()nie trim.strings()
usunąłem
89

Aby manipulować białą spacją, użyj str_trim () w pakiecie stringr. Podręcznik ma datę 15 lutego 2013 r. I jest w wersji CRAN. Funkcja może również obsługiwać wektory łańcuchowe.

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

(podziękowania dla komentatora: R. Cotton)

userJT
źródło
2
To rozwiązanie usunęło trochę zmutowanych białych znaków, których trimws()nie można było usunąć.
Richard Telford,
1
@RichardTelford czy możesz podać przykład? Ponieważ można to uznać za błąd w trimws.
wligtenberg
IMO to najlepsze rozwiązanie. Niewiele kodu i wysoka wydajność
Peter
Dzięki za wymagany (stringr) ich dokumentacja lub przykłady nie zawierały wymaganego wiersza kodu!
pgee70
23

Prosta funkcja usuwania początkowych i końcowych białych znaków:

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

Stosowanie:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"
Bernhard Kausler
źródło
11

ad1) Aby zobaczyć białe spacje, możesz bezpośrednio wywołać print.data.framezmodyfikowane argumenty:

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"

Zobacz także ?print.data.frameinne opcje.

Marek
źródło
9

Użyj grep lub grepl, aby znaleźć obserwacje z białymi spacjami i sub, aby się ich pozbyć.

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
źródło
7
Lub, nieco bardziej zwięźle,"^\\s+|\\s+$"
hadley
4
Chciałem tylko zaznaczyć, że trzeba będzie użyć gsubzamiast subwyrażenia regularnego Hadleya. Dzięki subniemu znikną końcowe białe znaki tylko wtedy, gdy nie będzie wiodących białych znaków ...
f3lix
Nie wiedziałem, że możesz użyć \ s itp. Z perl = FALSE. Dokumenty mówią, że w takim przypadku używana jest składnia POSIX, ale zaakceptowana składnia jest tak naprawdę nadzbiorem zdefiniowanym przez bibliotekę wyrażeń
Jyotirmoy Bhattacharya
5

Wolałbym dodać odpowiedź jako komentarz do użytkownika 56, ale nie mogę tego napisać jako niezależnej odpowiedzi. Usunięcie początkowych i końcowych spacji można również osiągnąć za pomocą funkcji trim () z pakietu gdata:

require(gdata)
example(trim)

Przykład użycia:

> trim("   Remove leading and trailing blanks    ")
[1] "Remove leading and trailing blanks"
KAA
źródło
5

Kolejny powiązany problem występuje, jeśli między wejściami jest wiele spacji:

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

Następnie możesz łatwo podzielić ten ciąg na „rzeczywiste” tokeny, używając wyrażenia regularnego do splitargumentu:

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

Zauważ, że jeśli istnieje dopasowanie na początku (niepustego) ciągu, pierwszym elementem wyniku jest „” „”, ale jeśli istnieje dopasowanie na końcu łańcucha, wynik jest taki sam jak z usuniętym dopasowaniem.

TMOTTM
źródło
5

Inną opcją jest użycie stri_trimfunkcji z stringipakietu, która domyślnie usuwa początkowe i końcowe białe znaki:

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

Aby usunąć tylko wiodące białe znaki, użyj stri_trim_left. Aby usunąć tylko końcowe białe znaki, użyj stri_trim_right. Jeśli chcesz usunąć inne wiodące lub końcowe znaki, musisz to określić za pomocą pattern =.

Zobacz także, ?stri_trimaby uzyskać więcej informacji.

Jaap
źródło
2

Utworzyłem trim.strings ()funkcję przycinania początkowych i / lub końcowych białych znaków jako:

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

Dla ilustracji

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
źródło
1

Najlepszą metodą jest trimws ()

Poniższy kod zastosuje tę funkcję do całej ramki danych

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

Santosh Kadge
źródło
lub df[] <- lapply(df, trimws)być bardziej kompaktowym. Ale w obu przypadkach wymusi kolumny do postaci. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)być bezpiecznym.
Moody_Mudskipper
1

Próbowałem trim (). Działa dobrze z białymi spacjami oraz „\ n”. x = '\ n Harden, J. \ n'

wykończenie (x)

J.Dan
źródło
0
myDummy[myDummy$country == "Austria "] <- "Austria"

Następnie musisz zmusić R, aby nie rozpoznawał „Austrii” jako poziomu. Udawajmy, że masz również poziomy „USA” i „Hiszpania”:

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

Trochę mniej onieśmielające niż najwyższa głosowana odpowiedź, ale powinno nadal działać.

David Mitchell
źródło