在R中使用gsub提取空格之前的字符字符串

64
我有一个生日列表,看起来像这样:
dob <- c("9/9/43 12:00 AM/PM", "9/17/88 12:00 AM/PM", "11/21/48 12:00 AM/PM")

我希望从此变量中仅获取日历日期(即删除第一个空格之后的所有内容)。

以下是我迄今为止尝试过的方法:

dob.abridged <- substring(dob,1,8)
dob
[1] "9/9/43 1" "9/17/88 " "11/21/48"
dob.abridged <- gsub(" $","", dob.abridged, perl=T)
> dob.abridged
[1] "9/9/43 1" "9/17/88"  "11/21/48"

我的代码适用于长度为 6 或 7 的日历日期,但不适用于长度为 8 的日期。有没有更有效的正则表达式来处理长度为 6、7 或 8 的日历日期,并可与 gsub 一起使用的提示呢?
谢谢。
5个回答

139

不需要使用substring函数,直接使用gsub函数:

gsub( " .*$", "", dob )
# [1] "9/9/43"   "9/17/88"  "11/21/48"
表示一个空格,然后使用.匹配任何字符,使用*表示前一个字符出现任意次数,直到字符串的结尾$。请参见?regex学习正则表达式。

5
我能分享的唯一建议是只需使用“sub”,因为只有一个字符串结束位置。 - Wiktor Stribiżew

17

stringr包含一个专门为此问题量身定制的函数。

library(stringr)
word(dob,1)
# [1] "9/9/43"   "9/17/88"  "11/21/48"

5
将第二个参数更改为-1,可提取最后一个空格后面的文本,这正是我想要的。即word(dob,-1) - dpel

17

我经常使用strsplit来解决这类问题,但很喜欢Romain的答案之简单。我认为将Romain的解决方案与strsplit的答案进行比较会很有趣:

下面是strsplit的解决方案:

sapply(strsplit(dob, "\\s+"), "[", 1)

使用microbenchmark包和dob < - rep(dob, 1000)来测试原始数据:

Unit: milliseconds
                                    expr       min        lq    median
                   gsub(" .*$", "", dob)  4.228843  4.247969  4.258232
 sapply(strsplit(dob, "\\\\s+"), "[", 1) 14.438241 14.558832 14.634638
        uq       max neval
  4.268029  5.081608  1000
 14.756628 53.344984  1000

在Windows 7机器上,清晰的赢家是Romain的gsub正则表达式。感谢您的回答和解释,Romain。


1

从空格前提取字母的另一种方法是:

您需要安装“stringr”软件包。

stringr::str_extract(c("juan carlos", "miguel angel"), stringr::regex(pattern = "[a-z]+(?=\\s)", ignore_case = F))

[a-z]: 匹配在Unicode代码点顺序中a和z之间的每个字符。

+: 1个或更多。

(?=\\s): 向前查找,后跟\s(即空格)(不匹配\s)。

更多信息:https://stringr.tidyverse.org/articles/regular-expressions.html


-1

另一个正则表达式模式,仅提取日期

library(stringr)
str_extract(dob, regex("\\d{1,}\\/\\d{1,}\\/\\d{1,}"))
#[1] "9/9/43"   "9/17/88"  "11/21/48"
  • \\d{1,}: 匹配至少1次数字
  • \\/: 转义正斜杠

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