Comment découper les espaces blancs avant et arrière?

360

J'ai des problèmes avec les espaces blancs de début et de fin dans un data.frame. Par exemple, j'aime jeter un oeil à un spécifique rowdans une data.framebase sur une certaine condition:

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

Je me demandais pourquoi je n'obtenais pas la production attendue car le pays que l'Autriche existait évidemment dans mon pays data.frame. Après avoir parcouru l'historique de mon code et essayé de comprendre ce qui n'allait pas, j'ai essayé:

> 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

Tout ce que j'ai changé dans la commande est un espace supplémentaire après l'Autriche.

D'autres problèmes gênants se posent évidemment. Par exemple, lorsque j'aime fusionner deux cadres en fonction de la colonne du pays. On data.frameutilise "Austria "alors que l'autre a "Austria". La correspondance ne fonctionne pas.

  1. Existe-t-il un bon moyen de «montrer» l'espace sur mon écran afin que je sois conscient du problème?
  2. Et puis-je supprimer les espaces blancs avant et arrière dans R?

Jusqu'à présent, j'avais l'habitude d'écrire un Perlscript simple qui supprime l'espace, mais ce serait bien si je pouvais le faire à l'intérieur de R.

mropa
la source
1
Je viens de voir que sub()la Perlnotation est également utilisée. Désolé pour ça. Je vais essayer d'utiliser la fonction. Mais pour ma première question, je n'ai pas encore de solution.
mropa
4
Comme l'avait souligné Hadley, cette expression régulière "^ \\ s + | \\ s + $" identifiera les espaces blancs de début et de fin. donc x <- gsub ("^ \\ s + | \\ s + $", "", x) de nombreuses fonctions de lecture de R ont cette option: strip.white = FALSE
Jay

Réponses:

456

La meilleure façon est probablement de gérer les espaces de fin lorsque vous lisez votre fichier de données. Si vous utilisez read.csvou read.tablevous pouvez définir le paramètre strip.white=TRUE.

Si vous souhaitez nettoyer les chaînes par la suite, vous pouvez utiliser l'une de ces fonctions:

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

Pour utiliser l'une de ces fonctions sur myDummy$country:

 myDummy$country <- trim(myDummy$country)

Pour «montrer» l'espace blanc que vous pouvez utiliser:

 paste(myDummy$country)

qui vous montrera les chaînes entourées de guillemets (") facilitant la repérage des espaces.

f3lix
la source
7
Comme l'avait souligné Hadley, cette expression régulière "^ \\ s + | \\ s + $" identifiera les espaces blancs de début et de fin. donc x <- gsub ("^ \\ s + | \\ s + $", "", x) de nombreuses fonctions de lecture de R comme cette option: strip.white = FALSE
Jay
50
Voir également str_trimdans le stringrpackage.
Richie Cotton
1
Plus un pour "la fonction Trim maintenant stockée pour une utilisation future" - merci!
Chris Beeley
4
Malheureusement, strip.white = TRUE ne fonctionne que sur les chaînes non citées.
Rodrigo
2
Il existe un moyen beaucoup plus simple de rogner les espaces dans R 3.2.0. Voir la réponse suivante!
Alex
519

Depuis R 3.2.0, une nouvelle fonction a été introduite pour supprimer les espaces blancs avant / arrière:

trimws()

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

wligtenberg
la source
2
Cela dépend de la définition d'une meilleure réponse. Cette réponse est agréable à connaître (+1) mais dans un test rapide, elle n'était pas aussi rapide que certaines des alternatives disponibles.
A5C1D2H2I1M1N2O1R2T1
ne semble pas fonctionner pour les chaînes multi-lignes, bien qu'il \nsoit dans la classe des caractères couverts. trimws("SELECT\n blah\n FROM foo;")contient toujours des nouvelles lignes.
Jubbles
6
@Jubbles C'est le comportement attendu. Dans la chaîne que vous passez aux trimws, il n'y a pas d'espaces blancs de début ou de fin. Si vous souhaitez supprimer les espaces blancs de début et de fin de chacune des lignes de la chaîne, vous devrez d'abord la diviser. Comme ceci: trimws (strsplit ("SELECT \ n blah \ n FROM foo;", "\ n") [[1]])
wligtenberg
1
Bien qu'il soit une fonction intégrée pour les versions récentes de R, il fait juste une expression régulière de style PERL sous le capot. J'aurais pu m'attendre à un code C personnalisé rapide pour le faire. Peut-être que l' trimwsexpression régulière est assez rapide. stringr::str_trim(basé sur stringi) est également intéressant en ce qu'il utilise une bibliothèque de chaînes internationalisée complètement indépendante. On pourrait penser que les espaces blancs seraient à l'abri des problèmes d'internationalisation, mais je me demande. Je n'ai jamais vu de comparaison entre les résultats natifs et stringr/ stringiou les benchmarks.
Jack Wasey
Pour une raison quelconque, je ne pouvais pas comprendre, trimws()n'a pas supprimé mes principaux espaces blancs, tandis que ceux de Bryan trim.strings()ci - dessous (seulement 1 vote, le mien!) L'ont fait ...
PatrickT
89

Pour manipuler l'espace blanc, utilisez str_trim () dans le package stringr. Le paquet a un manuel daté du 15 février 2013 et est en CRAN. La fonction peut également gérer des vecteurs de chaîne.

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

(le mérite revient au commentateur: R. Cotton)

userJT
la source
2
Cette solution a supprimé certains espaces mutants qui trimws()n'ont pas pu être supprimés.
Richard Telford
1
@RichardTelford pourriez-vous donner un exemple? Parce que cela pourrait être considéré comme un bug dans les trimws.
wligtenberg
OMI c'est la meilleure solution. Pas beaucoup de code et très performant
Peter
Merci pour l'exigence (stringr) leur documentation ou leurs exemples n'avaient pas cette ligne de code requise!
pgee70
23

Une fonction simple pour supprimer les espaces blancs de début et de fin:

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

Usage:

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

ad1) Pour voir les espaces blancs, vous pouvez appeler directement print.data.frameavec des arguments modifiés:

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"

Voir aussi ?print.data.framepour d'autres options.

Marek
la source
9

Utilisez grep ou grepl pour trouver des observations avec des espaces blancs et sub pour vous en débarrasser.

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
la source
7
Ou, un peu plus succinctement,"^\\s+|\\s+$"
hadley
4
Je voulais juste souligner que l'on devra utiliser à la gsubplace de subl'expression rationnelle de hadley. Avec subcela, les espaces de fin ne seront supprimés que s'il n'y a pas d'espaces de tête ...
f3lix
Je ne savais pas que vous pouviez utiliser \ s etc. avec perl = FALSE. Les documents disent que la syntaxe POSIX est utilisée dans ce cas, mais la syntaxe acceptée est en fait un sur-ensemble défini par la bibliothèque TRE regex laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Bhattacharya
5

Je préfère ajouter la réponse en tant que commentaire à user56, mais je ne peux pas l'écrire comme une réponse indépendante. La suppression des blancs de début et de fin peut également être obtenue grâce à la fonction trim () du package gdata:

require(gdata)
example(trim)

Exemple d'utilisation:

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

Un autre problème connexe se produit si vous avez plusieurs espaces entre les entrées:

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

Vous pouvez ensuite facilement diviser cette chaîne en "vrais" jetons en utilisant une expression régulière à l' splitargument:

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

Notez que s'il y a une correspondance au début d'une chaîne (non vide), le premier élément de la sortie est '""', mais s'il y a une correspondance à la fin de la chaîne, la sortie est la même que avec le match supprimé.

TMOTTM
la source
5

Une autre option consiste à utiliser la stri_trimfonction du stringipackage qui par défaut supprime les espaces de début et de fin:

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

Pour supprimer uniquement les espaces blancs de début, utilisez stri_trim_left. Pour supprimer uniquement les espaces de fin, utilisez stri_trim_right. Lorsque vous souhaitez supprimer d'autres caractères de début ou de fin, vous devez spécifier cela avecpattern = .

Voir aussi ?stri_trimpour plus d'informations.

Jaap
la source
2

J'ai créé une trim.strings ()fonction pour couper les espaces de début et / ou de fin comme:

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

Pour illustration,

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
la source
1

La meilleure méthode est trimws ()

Le code suivant appliquera cette fonction à l'ensemble de la trame de données

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

Santosh Kadge
la source
ou df[] <- lapply(df, trimws)pour être plus compact. Mais dans les deux cas, il contraindra les colonnes à être personnalisées. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)pour être sûr.
Moody_Mudskipper
1

J'ai essayé le trim (). Fonctionne bien avec les espaces blancs ainsi que le '\ n'. x = '\ n Harden, J. \ n'

garniture (x)

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

Après cela, vous devrez forcer R à ne pas reconnaître "Autriche" comme niveau. Imaginons que vous ayez également "USA" et "Espagne" comme niveaux:

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

Un peu moins intimidant que la réponse la plus élevée, mais cela devrait quand même fonctionner.

David Mitchell
la source