Як обрізати пробіли та пробіли?


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сценарій, який видаляє пробіл, але було б добре, якщо я можу якось це зробити всередині Р.


1
Я щойно бачив, що також sub()використовується Perlпозначення. Вибач за те. Я спробую використати функцію. Але для мого першого питання у мене поки немає рішення.
mropa

4
Як Хадлі вказував, цей регулярний вираз "^ \\ s + | \\ s + $" визначить провідну та відсталу пробіли. так x <- gsub ("^ \\ s + | \\ s + $", "", x) багато функцій читання R, як мають цю опцію: strip.white = ЛАЖНИЙ
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)

який покаже вам рядки, оточені лапками ("), що полегшує простеження пробілів.


7
Як Хадлі вказував, цей регулярний вираз "^ \\ s + | \\ s + $" визначить провідну та відсталу пробіли. тому x <- gsub ("^ \\ s + | \\ s + $", "", x) багато функцій зчитування R мають такі параметри: strip.white = FALSE
Jay

50
Дивіться також str_trimв stringrупаковці.
Річі Коттон

1
Плюс один для "Функція Trim тепер зберігається для подальшого використання" - дякую!
Кріс Білі

4
На жаль, strip.white = ІСТИНА працює лише на рядках, які не котируються.
Родріго

2
Існує набагато простіший спосіб обрізати пробіл у R 3.2.0. Дивіться наступну відповідь!
Олексій

519

З R 3.2.0 була введена нова функція для видалення проміжних / задніх пробілів:

trimws()

Дивіться: http://stat.ethz.ch/R-manual/R-patched/library/base/html/trimws.html


2
Це залежить від визначення найкращої відповіді. Цю відповідь приємно знати (+1), але у швидкому тесті це було не так швидко, як деякі альтернативи там.
A5C1D2H2I1M1N2O1R2T1

здається, не працює для багаторядкових рядків, незважаючи на \nте , що вони перебувають у накритому символьному класі trimws("SELECT\n blah\n FROM foo;")все ще містить нові рядки.
Jubbles

6
@Jubbles Така очікувана поведінка. У рядку, який ви переходите до обрізки, немає провідних або кінцевих пробілів. Якщо ви хочете видалити провідні та кінцеві пробіли з кожного з рядків рядка, спочатку доведеться розділити його. Ось так: trimws (strsplit ("SELECT \ n blah \ n FOO;", "\ n") [[1]])
wligtenberg

1
Хоча вбудована функція для останніх версій R, вона "просто" робить регулярний вираз у стилі PERL під кришкою. Я, можливо, очікував, що це швидко зробить спеціальний код С для цього. Можливо, 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)

(кредит надходить до коментатора: Р. Коттон)


2
Це рішення видалило кілька мутантних пробілів, які trimws()не вдалося видалити.
Річард Телфорд

1
@RichardTelford Ви могли б навести приклад? Тому що це може вважатися помилкою в trimws.
wligtenberg

ІМО це найкраще рішення. Не так багато коду та високоефективних
Пітер

Дякуємо за вимогу (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інші варіанти.


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

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

require(gdata)
example(trim)

Приклад використання:

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

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"

Зауважте, що якщо є збіг на початку (не порожній) рядка, першим елементом виводу є "" "', але якщо є відповідність у кінці рядка, вихід буде таким самим, як із вилученою сіркою


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"   

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 Гарден, Дж. \ n'

обрізка (х)


0
myDummy[myDummy$country == "Austria "] <- "Austria"

Після цього вам потрібно змусити R не визнавати "Австрію" рівнем. Зробимо вигляд, що у вас також є "США" та "Іспанія" як рівні:

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

Трохи менш залякуючий, ніж відповідь, яка найбільше проголосувала, але все одно має працювати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.