4

我真的找不到一种优雅的方式来实现这一点,请帮忙。

我有一个DT数据表:

name,value
"lorem pear ipsum",4
"apple ipsum lorem",2
"lorem ipsum plum",6

并基于一个列表Fruits <- c("pear", "apple", "plum"),我想创建一个因子类型列。

name,value,factor
"lorem pear ipsum",4,"pear"
"apple ipsum lorem",2,"apple"
"lorem ipsum plum",6,"plum"

我想这是基本的,但我有点卡住了,这就是我走了多远:

DT[grep("apple", name, ignore.case=TRUE), factor := as.factor("apple")]

提前致谢。

4

3 回答 3

6

您可以使用正则表达式对其进行矢量化,例如使用gsub()

设置数据:

strings <- c("lorem pear ipsum", "apple ipsum lorem", "lorem ipsum plum")
fruit <- c("pear", "apple", "plum")

现在创建一个正则表达式

ptn <- paste0(".*(", paste(fruit, collapse="|"), ").*")
gsub(ptn, "\\1", strings)
[1] "pear"  "apple" "plum" 

正则表达式的工作原理是用 , 分隔每个搜索元素|,嵌入括号内:

ptn
[1] ".*(pear|apple|plum).*"

要在数据表中执行此操作,根据您的问题,那么简单如下:

library(data.table)
DT <- data.table(name=strings, value=c(4, 2, 6))
DT[, factor:=gsub(ptn, "\\1", strings)]
DT

                name value factor
1:  lorem pear ipsum     4   pear
2: apple ipsum lorem     2  apple
3:  lorem ipsum plum     6   plum
于 2013-03-07T18:24:50.987 回答
5

我不知道是否有更“data.table”的方式来做到这一点,但你可以试试这个:

DT[, factor := sapply(Fruits, function(x) Fruits[grep(x, name, ignore.case=TRUE)])]
DT
#                 name value factor
# 1:  lorem pear ipsum     4   pear
# 2: apple ipsum lorem     2  apple
# 3:  lorem ipsum plum     6   plum
于 2013-03-07T17:44:19.147 回答
2

这是我的编码解决方案。困难的部分是从regex. 我所知道的最好的通用解决方案(找到与任何正则表达式匹配的任何内容)是regexecandregmatches组合(见下文)。

# Create the data frame
name <- c("lorem pear ipsum", "apple ipsum lorem", "lorem ipsum plum")
value <- c(4,2,6)
DT <- data.frame(name=name, value=value, stringsAsFactors=FALSE)

# Create the regular expression
Fruits <- c("pear", "apple", "plum")
myRegEx <- paste(Fruits, collapse = "|")

# Find the matches
r <- regexec(myRegEx, DT$name, ignore.case = TRUE)
matches <- regmatches(DT$name, r)

# Extract the matches, convert to factors
factor <- sapply(matches, function(x) as.factor(x[[1]]))

# Add to data frame
DT$factor <- factor

这可能是比您想要的更长的解决方案。

于 2013-03-07T18:19:34.773 回答