使用grepl替换每个匹配的字符串时,如何简化以下代码?

问题描述 投票:0回答:2

我列出的文件名(data $ name)列如下:

aaa.doc
aaa.pptx
http://aaa
aaa.jpg
guide
some memo
...

我希望尽可能用所有类型替换它们,没有特定文件类型的名称我只会将其标记为“其他”。

用文件类型替换文件名列时,我这样做了:

data$name[grepl("http",data$name,ignore.case = FALSE)]<-"web"
data$name[grepl("pptx",data$name,ignore.case = FALSE)]<-"ppt"
data$name[grepl("pdf",data$name,ignore.case = FALSE)]<-"pdf"
data$name[grepl("txt",data$name,ignore.case = FALSE)]<-"txt"
...

1.如何简化这个还是有更好的方法吗?

2.如何替换与我列出的任何类型都不匹配的文件名?

例如:当文件名是指南时,我会用“其他”替换它。

谢谢。


请看我的问题:

> d <- structure(list(name = structure(c(1L, 3L, 5L, 2L, 4L, 7L, 6L), .Label = c("aaa.doc", "aaa.jpg", "aaa.pptx", "guide", "http://aaa", "memo", "some"), class = "factor")), class = "data.frame",row.names = c(NA, -7L))
> d
        name
1    aaa.doc
2   aaa.pptx
3 http://aaa
4    aaa.jpg
5      guide
6       some
7       memo
> trans <- c(http = "web", pptx = "ppt", pdf = "pdf", txt = "txt")
> pat <- paste(names(trans), collapse = "|")  # http|pptx|pdf|txt
> strapply(as.character(d$name), pat, ~ trans[x], empty = "others", simplify = TRUE)
[[1]]
NULL

[[2]]
[1] "pptx"

[[3]]
[1] "http"

[[4]]
NULL

[[5]]
NULL

[[6]]
NULL

[[7]]
NULL
r
2个回答
1
投票
  1. tidyverse方式,它可能看起来像下面。您可以为case_when()添加更多选项 库(tidyverse) data < - tibble(name = c('aaa.doc','aaa.pptx','aaa.txt','aaa.pdf','http:////aaa','aaa.jpg','guide','一些备忘录“)) data < - data%>%mutate(name = case_when(str_detect(tolower(name),“http”)〜“web”,str_detect(tolower(name),“pptx”)〜“ppt”,str_detect(tolower(name) ),“pdf”)〜“pdf”,str_detect(tolower(name),“txt”)〜“txt”,str_detect(tolower(name),“guide”)〜“other”,TRUE~'unknown'))
  2. TRUE应该是最后一行来处理所有其他情况。

1
投票

1)strapply定义一个命名向量trans,将匹配转换为类型。然后找到trans名称并使用strapply翻译每个名称。

strapply的第一个参数是输入字符向量,第二个是要匹配的模式,第三个是应用于此处使用公式表示法表示的匹配的函数,empty参数指定在没有匹配时使用的内容和simplify=TRUE原因它输出一个普通的字符向量而不是列表。

library(gsubfn)

trans <- c(http = "web", pptx = "ppt", pdf = "pdf", txt = "txt")

pat <- paste(names(trans), collapse = "|")  # http|pptx|pdf|txt
strapply(tolower(d$name), pat, ~ trans[x], empty = "others", simplify = TRUE)
## [1] "others" "ppt"    "web"    "others" "others" "others" "others"

2)Base R使用上面的trans我们可以创建一个简单的循环。

result <- result.ini <- tolower(d$name)
for(nm in names(trans)) result[ grepl(nm, result) ] <- trans[nm]
result[ result == result.ini ] <- "others"
result
## [1] "others" "ppt"    "web"    "others" "others" "others" "others"

3)R Base - Reduce我们可以使用Reduce,其方式与for循环基本相同,但没有显式循环:

Match <- function(result, nm) ifelse(grepl(nm, result), trans[nm], result)
out <- Reduce(Match, names(trans), init = tolower(d$name))
out[out == tolower(d$name)] <- "others"
out
## [1] "others" "ppt"    "web"    "others" "others" "others" "others"

注意

可重复输入的输入:

d <- 
structure(list(name = structure(c(1L, 3L, 5L, 2L, 4L, 7L, 6L), .Label = c("aaa.doc", 
"aaa.jpg", "aaa.pptx", "guide", "http://aaa", "memo", "some"), 
class = "factor")), class = "data.frame", row.names = c(NA, -7L))
© www.soinside.com 2019 - 2024. All rights reserved.