使用gsub和正则表达式提取特定单词

5

从之前的问题中跳出来,我遇到了一个问题,即如何使用正确的正则表达式语法来隔离特定的单词。

给定一个数据框:

DL<-c("Dark_ark","Light-Lis","dark7","DK_dark","The_light","Lights","Lig_dark","D_Light")
Col1<-c(1,12,3,6,4,8,2,8)
DF<-data.frame(Col1)
row.names(DF)<-DL

我希望提取行名称中的所有“Dark” 和 “Light”(忽略大小写),并创建第二列仅包含字符串“Dark”或“Light”。

Col2<-c("Dark","Light","dark","dark","light","Light","dark","Light")
DF$Col2<-Col2

          Col1  Col2
Dark_ark     1  Dark
Light-Lis   12 Light
dark7        3  dark
DK_dark      6  dark
The_light    4 light
Lights       8 Light
Lig_dark     2  dark
D_Light      8 Light

我稍微修改了原始数据以详细说明我的当前问题。在Tyler Rinker给出的优秀答案的启发下,我使用了以下代码:

DF$Col2<-gsub("[^dark|light]", "", row.names(DF), ignore.case = TRUE)

但是gsub对一些常用字母有误判。在论坛上搜索使用正则表达式隔离确切单词的答案时,似乎应该使用双斜杠和

\\<light\\>

或者

\\blight\\b

所以,为什么会出现这条线呢?
DF$Col2<-gsub("[^\\<dark\\>|\\<light\\>]", "", row.names(DF), ignore.case = TRUE)

没有获取所需的列吗?而是我得到了
          Col1    Col2
Dark_ark     1 Darkark
Light-Lis   12 LightLi
dark7        3    dark
DK_dark      6  DKdark
The_light    4 Thlight
Lights       8   Light
Lig_dark     2 Ligdark
D_Light      8  DLight

1
如果问题不是ssce,没有人会回答正则表达式的问题。 - aaronman
1
首先,\\b 用于定义单词边界。因此,您必须告诉它确切的字符串在哪里。据我所知,您不能否定它。其次,它使用空格和标点符号来查找边界... _ 不是其中之一。 - Arun
2个回答

9
这个怎么样?
unlist(regmatches(rownames(DF), gregexpr("dark|light", rownames(DF), ignore.case=TRUE)))
# [1] "Dark"  "Light" "dark"  "dark"  "light" "Light" "dark"  "Light"

或者

gsub(".*(dark|light).*$", "\\1", row.names(DF), ignore.case = TRUE)
# [1] "Dark"  "Light" "dark"  "dark"  "light" "Light" "dark"  "Light"

虽然在一般实践中稍微有些风险,但由于 as.character 的工作方式,您可以将第一个函数写成:tolower(regmatches(rownames(DF), gregexpr("dark|light", rownames(DF), ignore.case=TRUE))) - thelatemail
...而第二种方法可能会给出更一致的结果:gsub(".*(dark|light).*$", "\\1", tolower(row.names(DF))) - thelatemail
@thelatemail,OP所展示的输出例如包含“Dark”和“dark”,这取决于行名称中哪一个存在。因此答案中没有使用tolower函数。 - Arun
这是正确的,但它也说:“我想从行名称中提取所有的“Dark”和“Light”(忽略大小写),并创建一个包含字符串“Dark”或“Light”的第二列”。 - thelatemail
句子的第一部分(大写 vs 小写)是用于提取,而不是替换。句子的第二部分与 OP 的输出明显相矛盾。无论如何,tolower 不会给出 "Dark" 和 "Light",而是会给出 "dark" 和 "light"。 - Arun

5

其中一种选择是使用 stringr 包:

library(stringr) 
str_extract(tolower(rownames(DF)),'dark|light')
[1] "dark"  "light" "dark"  "dark"  "light" "light" "dark"  "light"

或者更好的方法是使用 @Arun 的建议:
str_extract(rownames(DF), ignore.case('dark|light'))

2
agstudy,看起来你可以这样做:str_extract(rownames(DF), ignore.case('dark|light')) - Arun

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