¿Cómo recortar los espacios en blanco iniciales y finales?

360

Tengo algunos problemas con los espacios en blanco iniciales y finales en un data.frame. Por ejemplo, me gusta echar un vistazo a un específico rowen data.framefunción de una determinada condición:

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

Me preguntaba por qué no obtuve la producción esperada ya que el país Austria obviamente existía en mi data.frame. Después de revisar mi historial de código e intentar averiguar qué salió mal, intenté:

> 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

Todo lo que he cambiado en el comando es un espacio en blanco adicional después de Austria.

Obviamente surgen problemas molestos. Por ejemplo, cuando me gusta fusionar dos cuadros en función de la columna del país. Uno data.frameusa "Austria "mientras que el otro marco tiene "Austria". La coincidencia no funciona.

  1. ¿Hay una buena manera de "mostrar" el espacio en blanco en mi pantalla para que sea consciente del problema?
  2. ¿Y puedo eliminar los espacios en blanco iniciales y finales en R?

Hasta ahora solía escribir un Perlscript simple que elimina el espacio en blanco, pero sería bueno si de alguna manera puedo hacerlo dentro de R.

mropa
fuente
1
Acabo de ver que también sub()usa la Perlnotación. Lo siento por eso. Voy a intentar usar la función. Pero para mi primera pregunta todavía no tengo una solución.
mropa
44
Como Hadley señaló, esta expresión regular "^ \\ s + | \\ s + $" identificará los espacios en blanco iniciales y finales. entonces x <- gsub ("^ \\ s + | \\ s + $", "", x) muchas de las funciones de lectura de R que tienen esta opción: strip.white = FALSE
Jay

Respuestas:

456

Probablemente, la mejor manera es manejar los espacios en blanco al leer su archivo de datos. Si usa read.csvo read.tablepuede establecer el parámetrostrip.white=TRUE .

Si desea limpiar las cadenas después, puede usar una de estas funciones:

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

Para usar una de estas funciones en myDummy$country:

 myDummy$country <- trim(myDummy$country)

Para 'mostrar' el espacio en blanco que podría usar:

 paste(myDummy$country)

que le mostrará las cadenas entre comillas (") haciendo que los espacios en blanco sean más fáciles de detectar.

f3lix
fuente
77
Como Hadley señaló, esta expresión regular "^ \\ s + | \\ s + $" identificará los espacios en blanco iniciales y finales. entonces x <- gsub ("^ \\ s + | \\ s + $", "", x) muchas de las funciones de lectura de R que tienen esta opción: strip.white = FALSE
Jay
50
Ver también str_trimen el stringrpaquete.
Richie Cotton
1
Más uno para "Función de recorte ahora almacenada para uso futuro" - ¡gracias!
Chris Beeley
44
Desafortunadamente, strip.white = TRUE solo funciona en cadenas no citadas.
Rodrigo
2
Hay una forma mucho más fácil de recortar espacios en blanco en R 3.2.0. ¡Mira la próxima respuesta!
Alex
519

A partir de R 3.2.0 se introdujo una nueva función para eliminar espacios en blanco iniciales / finales:

trimws()

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

wligtenberg
fuente
2
Depende de la definición de una mejor respuesta. Es bueno saber esta respuesta (+1) pero en una prueba rápida, no fue tan rápida como algunas de las alternativas disponibles.
A5C1D2H2I1M1N2O1R2T1
no parece funcionar para cadenas de varias líneas, a pesar de \nestar en la clase de caracteres cubiertos. trimws("SELECT\n blah\n FROM foo;")Todavía contiene nuevas líneas.
Jubbles
66
@Jubbles Ese es el comportamiento esperado. En la cadena que pasa a los recortes no hay espacios en blanco iniciales o finales. Si desea eliminar los espacios en blanco iniciales y finales de cada una de las líneas de la cadena, primero deberá dividirla. De esta manera: trimws (strsplit ("SELECT \ n blah \ n FROM foo;", "\ n") [[1]])
wligtenberg
1
Aunque es una función incorporada para versiones recientes de R, "solo" hace una expresión regular de estilo PERL debajo del capó. Podría haber esperado un código C personalizado rápido para hacer esto. Tal vez la trimwsexpresión regular es lo suficientemente rápida. stringr::str_trim(basado en stringi) también es interesante porque utiliza una biblioteca de cadenas internacionalizada completamente independiente. Uno pensaría que el espacio en blanco sería inmune a los problemas con la internacionalización, pero me pregunto. Nunca he visto una comparación de resultados de nativos vs stringr/ stringio cualquier punto de referencia.
Jack Wasey
Por alguna razón no pude entender, trimws()no eliminé mis espacios en blanco principales, mientras que Bryan trim.strings()debajo (¡solo 1 voto, el mío!) Sí ...
PatrickT
89

Para manipular el espacio en blanco, use str_trim () en el paquete stringr. El paquete tiene un manual con fecha del 15 de febrero de 2013 y está en CRAN. La función también puede manejar vectores de cadena.

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

(el crédito es para el comentarista: R. Cotton)

userJT
fuente
2
Esta solución eliminó algunos espacios en blanco mutantes que trimws()no se pudieron eliminar.
Richard Telford el
1
@ RichardTelford, ¿podría dar un ejemplo? Porque eso podría considerarse un error en trimws.
wligtenberg
OMI, esta es la mejor solución. No hay mucho código y tiene un alto rendimiento
Peter
¡Gracias por requerir (stringr) su documentación o ejemplos no tenían esta línea de código requerida!
pgee70
23

Una función simple para eliminar espacios en blanco iniciales y finales:

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

Uso:

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

ad1) Para ver espacios en blanco, puede llamar directamente print.data.framecon argumentos modificados:

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"

Ver también ?print.data.framepara otras opciones.

Marek
fuente
9

Use grep o grepl para encontrar observaciones con espacios en blanco y sub para deshacerse de ellos.

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
fuente
77
O, un poco más sucintamente,"^\\s+|\\s+$"
hadley
44
Solo quería señalar que tendrá que usarlo en gsublugar de subcon la expresión regular de hadley. Con subella se tira espacios en blanco sólo si no hay espacios en blanco que lleva ...
f3lix
No sabía que podía usar \ s, etc. con perl = FALSE. Los documentos dicen que la sintaxis POSIX se usa en ese caso, pero la sintaxis aceptada es en realidad un superconjunto definido por la biblioteca de expresiones
Jyotirmoy Bhattacharya
5

Prefiero agregar la respuesta como comentario al usuario56, pero aún así no puedo escribirlo como una respuesta independiente. La eliminación de espacios en blanco iniciales y finales también se puede lograr a través de la función trim () del paquete gdata:

require(gdata)
example(trim)

Ejemplo de uso:

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

Otro problema relacionado ocurre si tiene múltiples espacios entre las entradas:

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

Luego puede dividir fácilmente esta cadena en tokens "reales" utilizando una expresión regular para el splitargumento:

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

Tenga en cuenta que si hay una coincidencia al comienzo de una cadena (no vacía), el primer elemento de la salida es '""', pero si hay una coincidencia al final de la cadena, la salida es la misma que con el partido eliminado.

TMOTTM
fuente
5

Otra opción es usar la stri_trimfunción del stringipaquete que por defecto elimina los espacios en blanco iniciales y finales:

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

Para eliminar solo los espacios en blanco iniciales, use stri_trim_left. Para eliminar solo los espacios en blanco finales, use stri_trim_right. Cuando desee eliminar otros caracteres iniciales o finales, debe especificar eso conpattern = .

Ver también ?stri_trimpara más información.

Jaap
fuente
2

Creé una trim.strings ()función para recortar espacios en blanco iniciales y / o finales como:

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

Por ilustracion,

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
fuente
1

El mejor método es trimws ()

El siguiente código aplicará esta función a todo el marco de datos

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

Santosh Kadge
fuente
o df[] <- lapply(df, trimws)para ser más compacto. Pero en ambos casos obligará a las columnas al carácter. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)para estar seguro.
Moody_Mudskipper
1

Intenté recortar (). Funciona bien con espacios en blanco y con '\ n'. x = '\ n Endurecer, J. \ n'

recortar (x)

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

Después de esto, deberás forzar a R a no reconocer a "Austria" como un nivel. Supongamos que también tiene "Estados Unidos" y "España" como niveles:

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

Un poco menos intimidante que la respuesta más votada, pero aún así debería funcionar.

David Mitchell
fuente