如何去除字符串开头和结尾的空格?

415

我在处理一个data.frame时遇到了一些前后空格的问题。

例如,我根据某个条件查看data.frame中的特定row:

> 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 内部进行操作则更好。


1
我刚刚看到sub()同样使用了Perl符号。对此很抱歉。我将尝试使用这个函数。但对于我的第一个问题,我还没有解决方案。 - mropa
4
如 Hadley 所指出的,这个正则表达式“^\s+|\s+$”可以识别开头和结尾的空格。因此,x <- gsub("^\s+|\s+$", "", x)。许多 R 的读取函数也有此选项:strip.white = FALSE。 - Jay
15个回答

596

3
这取决于“最佳答案”的定义。这个答案很有用(+1),但在快速测试中,它不如其他一些替代方案快。 - A5C1D2H2I1M1N2O1R2T1
1
尽管\n在覆盖的字符类中,但似乎无法处理多行字符串。trimws("SELECT\n blah\n FROM foo;")仍然包含换行符。 - Jubbles
8
@Jubbles 这是预期行为。在你传递给 trimws 的字符串中,没有前导或尾随的空白字符。如果你想要从字符串中每一行的开头和结尾删除空白字符,你需要先将其拆分。像这样: trimws(strsplit("SELECT\n blah\n FROM foo;", "\n")[[1]]) - wligtenberg
1
虽然在最近的R版本中有一个内置函数,但它只是在底层执行PERL风格的正则表达式。我本来期望会有一些快速的自定义C代码来完成这个任务。也许trimws正则表达式已经足够快了。stringr::str_trim(基于stringi)也很有趣,因为它使用了一个完全独立的国际化字符串库。你可能认为空格符不会受到国际化问题的影响,但我还是有点担心。我从未见过原生结果与stringr/stringi或任何基准测试的比较。 - Jack Wasey
由于某些原因我无法理解,“trimws()”没有删除我的前导空格,而Bryan的“trim.strings()”(只有1票,是我的!)却可以... - PatrickT
1
@JackWasey 我已经添加了一个基准测试 - 这个例子可能有点简单,但它应该能够给出关于性能的想法。 - tjebo

488

处理行尾空格的最佳方法可能是在读取数据文件时处理。如果使用 read.csvread.table,您可以设置参数strip.white=TRUE

如果要在此之后清理字符串,可以使用以下函数之一:

# Returns string without leading white space
trim.leading <- function (x)  sub("^\\s+", "", x)

# Returns string without trailing white space
trim.trailing <- function (x) sub("\\s+$", "", x)

# Returns string without leading or trailing white space
trim <- function (x) gsub("^\\s+|\\s+$", "", x)

要在myDummy$country上使用这些函数之一:

 myDummy$country <- trim(myDummy$country)

要“显示”空白字符,您可以使用:

 paste(myDummy$country)

这将显示由引号(")包围的字符串,使空格更易于识别。


7
如Hadley所指出的,这个正则表达式“^\s+|\s+$”可以识别开头和结尾的空格。因此,x <- gsub("^\s+|\s+$", "", x)。许多R的读取函数也有这个选项:strip.white = FALSE。 - Jay
56
请参阅stringr包中的str_trim函数。 - Richie Cotton
2
加一分给“现在存储了Trim函数以备将来使用”- 谢谢! - Chris Beeley
4
很遗憾,strip.white=TRUE 只能用于非引号字符串。 - Rodrigo
2
在R 3.2.0中,有一种更简单的方法来修剪空格。请参见下一个答案! - Alex
显示剩余4条评论

96
使用stringr包中的str_trim()函数来处理空格。 该包的手册日期为2013年2月15日,可在CRAN上找到。 该函数还可以处理字符串向量。
install.packages("stringr", dependencies=TRUE)
require(stringr)
example(str_trim)
d4$clean2<-str_trim(d4$V2)

(感谢评论者:R. Cotton)


3
这个解决方案去掉了一些变异的空格,而 trimws() 无法去除这些空格。 - Richard Telford
2
@RichardTelford 能否提供一个例子?因为那可能被认为是 trimws 中的一个 bug。 - wligtenberg
在我看来,这是最佳解决方案。代码量不多且性能高效。 - Peter
感谢require(stringr)。他们的文档或示例中没有这个必需的代码行! - pgee70

28

一个简单的函数,用于删除前导和尾随空格:

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

用法:

> text = "   foo bar  baz 3 "
> trim(text)
[1] "foo bar  baz 3"

13

广告1)要查看空白区域,您可以直接使用修改后的参数调用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 以获取其他选项。


11

使用gdata包中的trim()函数也可以去除前导和尾随空格:

require(gdata)
example(trim)

使用示例:

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

我更愿意将答案作为对user56的评论添加,但由于无法这样做,所以作为独立答案编写。


11

使用grepgrepl查找具有空格的观测值,并使用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+$",意思是去除字符串开头和结尾的空格。 - hadley
4
想要指出的是,在使用Hadley的正则表达式时,必须使用gsub而不是sub。使用sub时,只有在没有前导空格的情况下才会剥离尾随空格... - f3lix
不知道你可以在perl=FALSE的情况下使用\s等。文档说在这种情况下使用POSIX语法,但实际上接受的语法是由TRE正则表达式库定义的超集http://laurikari.net/tre/documentation/regex-syntax/。 - Jyotirmoy Bhattacharya

6
另一种选择是使用来自stringi包的stri_trim函数,它默认删除前导和尾随空格: stri_trim
> x <- c("  leading space","trailing space   ")
> stri_trim(x)
[1] "leading space"  "trailing space"

仅删除前导空格,请使用 stri_trim_left。仅删除尾随空格,请使用 stri_trim_right。当您想要删除其他前导或尾随字符时,必须使用 pattern = 指定。请参见 ?stri_trim 以获取更多信息。

6

如果您在输入之间有多个空格,则可能会出现另一个相关的问题:

> 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
我创建了一个 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"   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接