У меня возникают проблемы с ведущими и конечными пробелами в 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"
. Соответствие не работает.
До сих пор я писал простой Perl
script, который удаляет пробелы, но было бы неплохо, если бы я мог как-то сделать это внутри R.
Вероятно, лучший способ - обработать конечные пробелы при чтении файла данных. Если вы используете 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)
который покажет вам строки, окруженные кавычками ("), которые упрощают определение пробелов.
Начиная с R 3.2.0 была введена новая функция для удаления ведущих/конечных пробелов:
trimws()
Смотрите: http://stat.ethz.ch/R-manual/R-patched/library/base/html/trimws.html
\n
находится в покрытом классе символов. trimws("SELECT\n blah\n FROM foo;")
прежнему содержит переводы строк.
Чтобы управлять пробелом, используйте str_trim() в пакете stringr. Пакет имеет руководство от 15 февраля 2011 года и находится в CRAN. Функция также может обрабатывать векторы строк.
install.packages("stringr", dependencies=TRUE)
require(stringr)
example(str_trim)
d4$clean2<-str_trim(d4$V2)
(кредит отправляется комментатору: R. Cotton)
trimws()
.
Простая функция для удаления начального и конечного пробелов:
trim <- function( x ) {
gsub("(^[[:space:]]+|[[:space:]]+$)", "", x)
}
Применение:
> text = " foo bar baz 3 "
> trim(text)
[1] "foo bar baz 3"
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
для других параметров.
Используйте grep или grepl, чтобы найти наблюдения с пробелами и суб, чтобы избавиться от них.
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"
"^\\s+|\\s+$"
gsub
вместо sub
с регулярным выражением hadley. С помощью sub
он удалит конечные пробелы, только если нет начальных пробелов ...
Я бы предпочел добавить ответ как комментарий пользователю56, но все же не смог написать в качестве независимого ответа. Удаление ведущих и завершающих пробелов может быть достигнуто с помощью функции trim() из пакета gdata:
require(gdata)
example(trim)
Пример использования:
> trim(" Remove leading and trailing blanks ")
[1] "Remove leading and trailing blanks"
Другим вариантом является использование функции 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
для получения дополнительной информации.
Другая связанная проблема возникает, если у вас есть несколько пробелов между входами:
> 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"
Обратите внимание, что если есть совпадение в начале a (непустая) строка, первый элемент вывода - "", но если в конце строки есть совпадение, то результатом является как и при удалении совпадения.
Лучший способ - trimws()
Следующий код будет применять эту функцию для всего кадра данных
mydataframe < - data.frame(lapply (mydataframe, trimws), strAsAsFactors = FALSE)
df[] <- lapply(df, trimws)
чтобы быть более компактным. Но это в обоих случаях приведёт столбцы к символу. df[sapply(df,is.character)] <- lapply(df[sapply(df,is.character)], trimws)
для безопасности.
myDummy[myDummy$country == "Austria "] <- "Austria"
После этого вам нужно заставить R не распознать "Австрию" как уровень. Предположим, вы также имеете "США" и "Испания" в качестве уровней:
myDummy$country = factor(myDummy$country, levels=c("Austria", "USA", "Spain"))
Немного менее устрашающе, чем самый высокий голос, проголосовавший, но он все равно должен работать.
Я создал функцию 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"
sub()
использует нотациюPerl
. Извини за это. Я собираюсь попытаться использовать функцию. Но по моему первому вопросу у меня пока нет решения.