Как обрезать начальные и конечные пробелы?

360

У меня проблемы с ведущими и конечными пробелами в data.frame. Например, я хотел бы взглянуть на конкретные rowв data.frameзависимости от определенного условия:

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

Мне было интересно, почему я не получил ожидаемый результат, поскольку в моей стране явно существовала Австрия data.frame. После просмотра истории кода и попытки выяснить, что пошло не так, я попытался:

> 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

Все, что я изменил в команде, это дополнительные пробелы после Австрии.

Дальнейшие досадные проблемы, очевидно, возникают. Например, когда мне нравится объединять два кадра на основе столбца страны. Один data.frameиспользует, "Austria "а другой имеет "Austria". Соответствие не работает.

  1. Есть ли хороший способ «показать» пробелы на моем экране, чтобы я знал о проблеме?
  2. И могу ли я удалить начальные и конечные пробелы в R?

До сих пор я писал простой Perlскрипт, который удаляет пробелы, но было бы неплохо, если бы я мог как-то сделать это внутри R.

mropa
источник
1
Я только что увидел, что sub()использует Perlобозначение, а также. Прости за это. Я собираюсь попытаться использовать функцию. Но по моему первому вопросу у меня пока нет решения.
Мропа
4
Как указал Хэдли, это регулярное выражение «^ \\ s + | \\ s + $» будет определять начальные и конечные пробелы. поэтому x <- gsub ("^ \\ s + | \\ s + $", "", x) многие из функций чтения R, так как имеют эту опцию: strip.white = FALSE
Jay

Ответы:

456

Вероятно, лучший способ - обработать замыкающие пробелы при чтении файла данных. Если вы используете read.csvили read.tableвы можете установить параметр strip.white=TRUE.

Если вы хотите очистить строки после этого, вы можете использовать одну из следующих функций:

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

Чтобы использовать одну из этих функций на myDummy$country:

 myDummy$country <- trim(myDummy$country)

Чтобы «показать» пробел, вы можете использовать:

 paste(myDummy$country)

которая покажет вам строки, заключенные в кавычки ("), чтобы легче было найти пробелы.

f3lix
источник
7
Как указал Хэдли, это регулярное выражение «^ \\ s + | \\ s + $» будет определять начальные и конечные пробелы. поэтому x <- gsub ("^ \\ s + | \\ s + $", "", x) многие из функций чтения R, так как имеют эту опцию: strip.white = FALSE
Jay
50
Смотрите также str_trimв stringrупаковке.
Ричи Коттон
1
Плюс еще один «Функция обрезки теперь сохранена для будущего использования» - спасибо!
Крис Били
4
К сожалению, strip.white = TRUE работает только со строками без кавычек.
Родриго
2
В R 3.2.0 есть намного более простой способ обрезать пробелы. Смотрите следующий ответ!
Алекс
519

Начиная с версии 3.2.0 была введена новая функция для удаления начальных / конечных пробелов:

trimws()

Смотрите: http://stat.ethz.ch/R-manual/R-patched/library/base/html/trimws.html

wligtenberg
источник
2
Это зависит от определения лучшего ответа. Этот ответ приятно знать о (+1), но в быстром тесте он был не так быстр, как некоторые альтернативы.
A5C1D2H2I1M1N2O1R2T1
похоже, не работает для многострочных строк, несмотря на \nто , что находится в покрытом классе символов. trimws("SELECT\n blah\n FROM foo;")до сих пор содержит новые строки.
Jubbles
6
@Jubbles Это ожидаемое поведение. В строке, которую вы передаете триммеру, нет пробелов в начале или в конце. Если вы хотите удалить начальные и конечные пробелы из каждой строки в строке, вам сначала придется разделить ее. Примерно так: trimws (strsplit ("SELECT \ n бла \ n ОТ foo;", "\ n") [[1]])
wligtenberg
1
Хотя встроенная функция для последних версий R, она «просто» выполняет регулярные выражения в стиле PERL. Я мог бы ожидать некоторый быстрый пользовательский код C, чтобы сделать это. Может быть, trimwsрегулярное выражение достаточно быстро. stringr::str_trim(на основе stringi) также интересен тем, что использует полностью независимую интернационализированную библиотеку строк. Можно подумать, что пробелы будут защищены от проблем с интернационализацией, но мне интересно. Я никогда не видел сравнения результатов нативных и stringr/ stringiили каких-либо тестов.
Джек Васи
По какой-то причине я не мог понять, trimws()не убрал свои ведущие пробелы, в то время как Брайан trim.strings()ниже (только 1 голос, мой!) Сделал ...
PatrickT
89

Чтобы манипулировать пробелами, используйте str_trim () в пакете stringr. Пакет имеет руководство от 15 февраля 2013 г. и находится в CRAN. Функция также может обрабатывать строковые векторы.

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

(благодарность комментатору: Р. Коттон)

userJT
источник
2
Это решение удалило некоторые мутантные пробелы, которые trimws()не удалось удалить.
Ричард Телфорд
1
@RichardTelford, не могли бы вы привести пример? Потому что это можно считать ошибкой в ​​триммерах.
Wligtenberg
ИМО это лучшее решение. Не много кода и высокая производительность
Питер
Спасибо за require (stringr), их документация или примеры не содержат этой обязательной строки кода!
pgee70
23

Простая функция для удаления начальных и конечных пробелов:

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

Применение:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"
Бернхард Кауслер
источник
11

ad1) Чтобы увидеть пробелы, вы можете напрямую вызвать print.data.frameс измененными аргументами:

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"

Смотрите также ?print.data.frameдля других вариантов.

Marek
источник
9

Используйте grep или grepl, чтобы найти наблюдения с пробелами и sub, чтобы избавиться от них.

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"  
Джотирмой Бхаттачарья
источник
7
Или, немного более кратко,"^\\s+|\\s+$"
Хэдли
4
Просто хотел бы отметить, что нужно будет использовать gsubвместо subрегулярного выражения Хэдли. С subего помощью
удаляются
Не знал, что вы можете использовать \ s и т. Д. С perl = FALSE. Документы говорят , что синтаксис POSIX используется в том случае, но синтаксис принят фактически надстройкой определяется TRE REGEX библиотека laurikari.net/tre/documentation/regex-syntax
Jyotirmoy Бхаттачарью
5

Я предпочел бы добавить ответ в качестве комментария к user56, но пока не могу писать как самостоятельный ответ. Удаление ведущих и конечных пробелов может быть достигнуто с помощью функции trim () из пакета gdata:

require(gdata)
example(trim)

Пример использования:

> trim("   Remove leading and trailing blanks    ")
[1] "Remove leading and trailing blanks"
KAA
источник
5

Другая связанная проблема возникает, если у вас есть несколько пробелов между входами:

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

Затем вы можете легко разбить эту строку на «настоящие» токены, используя регулярное выражение для splitаргумента:

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

Обратите внимание, что если есть совпадение в начале (непустой) строки, первый элемент выходных данных - это «» », но если в конце строки есть совпадение, выходные данные совпадают с со спичкой удалены.

TMOTTM
источник
5

Другой вариант - использовать stri_trimфункцию из stringiпакета, которая по умолчанию удаляет начальные и конечные пробелы:

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

Для удаления только начальных пробелов используйте stri_trim_left. Для удаления только конечных пробелов используйте stri_trim_right. Если вы хотите удалить другие начальные или конечные символы, вы должны указать это с помощью pattern =.

Смотрите также ?stri_trimдля получения дополнительной информации.

Яап
источник
2

Я создал trim.strings ()функцию для обрезки начальных и / или конечных пробелов как:

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

Для иллюстрации

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
источник
1

Лучший метод - trimws ()

Следующий код будет применять эту функцию ко всему фрейму данных

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

Сантош Кадге
источник
или df[] <- lapply(df, trimws)быть более компактным. Но это в обоих случаях приведет столбцы к символу. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)быть в безопасности.
Moody_Mudskipper
1

Я пытался обрезать (). Хорошо работает с пробелами, а также с \ n. x = '\ n Harden, J. \ n'

подрезать (х)

J.Dan
источник
0
myDummy[myDummy$country == "Austria "] <- "Austria"

После этого вам нужно заставить R не распознавать «Австрию» как уровень. Давайте представим, что у вас также есть "США" и "Испания" в качестве уровней:

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

Немного менее пугающе, чем ответ с наибольшим количеством голосов, но он все равно должен работать.

Дэвид Митчелл
источник