Como aparar espaços em branco à esquerda e à direita?

360

Estou tendo alguns problemas com espaços em branco iniciais e finais em um data.frame. Por exemplo, eu gosto de dar uma olhada em um específico rowem um com data.framebase em uma determinada condição:

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

Fiquei me perguntando por que não obtive a produção esperada desde que o país Áustria obviamente existia na minha data.frame. Depois de examinar meu histórico de códigos e tentar descobrir o que deu errado, tentei:

> 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

Tudo o que mudei no comando é um espaço em branco adicional após a Áustria.

Outros problemas irritantes obviamente surgem. Por exemplo, quando eu gosto de mesclar dois quadros com base na coluna do país. Um data.frameusa "Austria "enquanto o outro quadro tem "Austria". A correspondência não funciona.

  1. Existe uma boa maneira de 'mostrar' o espaço em branco na minha tela para que eu esteja ciente do problema?
  2. E posso remover o espaço em branco à esquerda e à direita no R?

Até agora, eu escrevia um Perlscript simples que remove o espaço em branco, mas seria bom se eu pudesse fazê-lo dentro de R.

mropa
fonte
11
Acabei de ver que sub()usa a Perlnotação também. Me desculpe por isso. Vou tentar usar a função Mas, para minha primeira pergunta, ainda não tenho uma solução.
Mropa
4
Como Hadley apontou, esse regex "^ \\ s + | \\ s + $" identificará os espaços em branco iniciais e finais. então x <- gsub ( "^ \\ s + | \\ s + $", "", x) muitas das funções de leitura de R como tem essa opção: strip.white = FALSE
Jay

Respostas:

456

Provavelmente, a melhor maneira é lidar com os espaços em branco à direita ao ler seu arquivo de dados. Se você usar read.csvou read.tablevocê pode definir o parâmetro strip.white=TRUE.

Se você quiser limpar as seqüências posteriormente, poderá usar uma destas funções:

# 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 uma dessas funções em myDummy$country:

 myDummy$country <- trim(myDummy$country)

Para 'mostrar' o espaço em branco que você pode usar:

 paste(myDummy$country)

que mostra as seqüências de caracteres entre aspas ("), facilitando a identificação dos espaços em branco.

f3lix
fonte
7
Como Hadley apontou, esse regex "^ \\ s + | \\ s + $" identificará os espaços em branco iniciais e finais. Portanto, x <- gsub ("^ \\ s + | \\ s + $", "", x) muitas das funções de leitura de R, pois possuem esta opção: strip.white = FALSE
Jay
50
Veja também str_trimno stringrpacote.
Richie Cotton
11
Mais um para "Função Trim agora armazenada para uso futuro" - obrigado!
precisa saber é o seguinte
4
Infelizmente, strip.white = TRUE funciona apenas em cadeias não citadas.
Rodrigo Rodrigo
2
Existe uma maneira muito mais fácil de aparar espaço em branco no R 3.2.0. Veja a próxima resposta!
29415 Alex
519

A partir do R 3.2.0, uma nova função foi introduzida para remover os espaços em branco à esquerda / à direita:

trimws()

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

Wligtenberg
fonte
2
Depende da definição de uma melhor resposta. É bom saber esta resposta (+1), mas em um teste rápido, não foi tão rápida quanto algumas das alternativas existentes.
A5C1D2H2I1M1N2O1R2T1
parece não funcionar para cadeias de linhas múltiplas, apesar de \npertencer à classe de caracteres cobertos. trimws("SELECT\n blah\n FROM foo;")ainda contém novas linhas.
Jubbles
6
@ Jubbles Esse é o comportamento esperado. Na sequência que você passa para as aparas, não há espaços em branco à esquerda ou à direita. Se você deseja remover os espaços em branco à esquerda e à direita de cada uma das linhas da sequência, primeiro será necessário dividi-lo. Assim: trimws (strsplit ("SELECT \ n blá \ n FROM foo;", "\ n") [[1]])
wligtenberg
11
Embora seja uma função interna para versões recentes do R, ela 'apenas' executa uma regex de estilo PERL sob o capô. Eu poderia esperar algum código C personalizado rápido para fazer isso. Talvez o trimwsregex seja rápido o suficiente. stringr::str_trim(com base em stringi) também é interessante, pois usa uma biblioteca de strings internacionalizada completamente independente. Você pensaria que o espaço em branco estaria imune a problemas com a internacionalização, mas eu me pergunto. Eu nunca vi uma comparação de resultados de nativos vs stringr/ stringiou quaisquer benchmarks.
precisa saber é o seguinte
Por alguma razão eu não conseguia descobrir, trimws()não remover meus principais espaços em branco, enquanto Bryan trim.strings()abaixo (apenas 1 voto, meu!) Fez ...
PatrickT
89

Para manipular o espaço em branco, use str_trim () no pacote stringr. O pacote tem manual datado de 15 de fevereiro de 2013 e está no CRAN. A função também pode manipular vetores de string.

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

(o crédito vai para o comentarista: R. Cotton)

userJT
fonte
2
Esta solução removeu alguns espaços em branco mutantes que trimws()não puderam ser removidos.
Richard Telford
11
@RichardTelford você poderia dar um exemplo? Porque isso pode ser considerado um bug no trimws.
wligtenberg
IMO, esta é a melhor solução. Não muito de código e altamente performance
Peter
Obrigado pela exigência (stringr), sua documentação ou exemplos não tinham essa linha de código necessária!
pgee70 18/03
23

Uma função simples para remover os espaços em branco iniciais e finais:

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

Uso:

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

ad1) Para ver espaços em branco, você pode chamar diretamente print.data.framecom 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"

Veja também ?print.data.framepara outras opções.

Marek
fonte
9

Use grep ou grepl para encontrar observações com espaços em branco e sub para se livrar deles.

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
fonte
7
Ou, um pouco mais sucintamente,"^\\s+|\\s+$"
hadley 14/02
4
Só queria salientar que esse terá que ser usado em gsubvez subdo regexp de hadley. Com subele irá retirar espaços em branco somente se não há nenhum líder espaço em branco ...
f3lix
Não sabia que você poderia usar \ s etc. com perl = FALSE. Os médicos dizem que a sintaxe POSIX é usado nesse caso, mas a sintaxe aceita é realmente um super definido pelo TRE regex biblioteca laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Bhattacharya
5

Prefiro adicionar a resposta como comentário ao user56, mas ainda assim não posso escrever como uma resposta independente. A remoção de espaços em branco à esquerda e à direita pode ser obtida através da função trim () do pacote gdata:

require(gdata)
example(trim)

Exemplo de uso:

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

Outro problema relacionado ocorre se você tiver vários espaços entre as entradas:

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

Você pode facilmente dividir essa sequência em tokens "reais" usando uma expressão regular para o splitargumento:

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

Observe que, se houver uma correspondência no início de uma sequência (não vazia), o primeiro elemento da saída será '""', mas se houver uma correspondência no final da sequência, a saída será a mesma que com a partida removida.

TMOTTM
fonte
5

Outra opção é usar a stri_trimfunção do stringipacote cujo padrão é remover os espaços em branco iniciais e finais:

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

Para remover apenas o espaço em branco à esquerda, use stri_trim_left. Para remover apenas o espaço em branco à direita, use stri_trim_right. Quando você deseja remover outros caracteres iniciais ou finais, é necessário especificar isso com pattern =.

Veja também ?stri_trimpara mais informações.

Jaap
fonte
2

Criei uma trim.strings ()função para aparar espaços em branco à esquerda e à direita 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)
    } 
} 

Para ilustração,

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

O melhor método é trimws ()

O código a seguir aplicará essa função a todo o quadro de dados

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

Santosh Kadge
fonte
ou df[] <- lapply(df, trimws)para ser mais compacto. Mas, em ambos os casos, forçará colunas a caracteres. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)estar seguro.
Moody_Mudskipper
1

Eu tentei aparar (). Funciona bem com espaços em branco e também com o '\ n'. x = '\ n Harden, J. \ n'

guarnição (x)

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

Depois disso, você precisará forçar R a não reconhecer "Áustria" como um nível. Vamos fingir que você também tem "EUA" e "Espanha" como níveis:

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

Um pouco menos intimidador do que a resposta mais votada, mas ainda deve funcionar.

David Mitchell
fonte