基于正则表达式创建新变量

amo*_*amo 15 regex r

我的问题涉及如何根据正则表达式的结果在R中的数据框上创建新变量.以下是数据的最小示例:

df <- data.frame(model=c("Legacy 2.0  BG5 B4 AUTO","Legacy 2.0 BH5 AT","Legacy 2.0i CVT Non Leather","Legacy 2.0i CVT","Legacy 2.0 BL5 AUTO B4",
                 "Legacy 2.0 BP5 AUTO","Legacy 2.0 BM5 AUTO CVT"), CRSP=c(3450000,3365000,4950000,5250000,4787526,3550000,5235000))

df
                        model    CRSP
1     Legacy 2.0  BG5 B4 AUTO 3450000
2           Legacy 2.0 BH5 AT 3365000
3 Legacy 2.0i CVT Non Leather 4950000
4             Legacy 2.0i CVT 5250000
5      Legacy 2.0 BL5 AUTO B4 4787526
6         Legacy 2.0 BP5 AUTO 3550000
7     Legacy 2.0 BM5 AUTO CVT 5235000
Run Code Online (Sandbox Code Playgroud)

我想创建一个新的变量'chassis',其值是相应的'model'变量字符串的第三个元素,因此最终得到:

df
                        model    CRSP chassis
1     Legacy 2.0  BG5 B4 AUTO 3450000     BG5
2           Legacy 2.0 BH5 AT 3365000     BH5
3 Legacy 2.0i CVT Non Leather 4950000     CVT
4             Legacy 2.0i CVT 5250000     CVT
5      Legacy 2.0 BL5 AUTO B4 4787526     BL5
6         Legacy 2.0 BP5 AUTO 3550000     BP5
7     Legacy 2.0 BM5 AUTO CVT 5235000     BM5
Run Code Online (Sandbox Code Playgroud)

我需要找到一种方法来提取每行中的相应元素并将它们放在新变量中.任何帮助将不胜感激.

Dav*_*urg 10

这是一个可能的解决方案 stringi

library(stringi)
df$chassis <- stri_extract_all_words(df$model, simplify = TRUE)[, 3]
df
#                         model    CRSP chassis
# 1     Legacy 2.0  BG5 B4 AUTO 3450000     BG5
# 2           Legacy 2.0 BH5 AT 3365000     BH5
# 3 Legacy 2.0i CVT Non Leather 4950000     CVT
# 4             Legacy 2.0i CVT 5250000     CVT
# 5      Legacy 2.0 BL5 AUTO B4 4787526     BL5
# 6         Legacy 2.0 BP5 AUTO 3550000     BP5
# 7     Legacy 2.0 BM5 AUTO CVT 5235000     BM5
Run Code Online (Sandbox Code Playgroud)

或者类似的

df$chassis <- sapply(stri_extract_all_words(df$model), `[`, 3)
Run Code Online (Sandbox Code Playgroud)


nic*_*ico 5

使用的替代解决方案 strsplit

# Split each of the models using space (the + accounts for multiple spaces)
# Note that model is a factor in your data frame, so it must be cast to char
model.split <- strsplit(as.character(df$model), " +")
# Now go through each element of the splitted list and get the 3rd word
df$chassis <- sapply(model.split, function(x){x[3]})
Run Code Online (Sandbox Code Playgroud)

  • 或者使用`data.table`的类似方法.`setDT(df)[,chassis:= tstrsplit(model,'+')[[3]]] []` (2认同)

Tyl*_*ker 5

对于这类任务,我是tidyr的忠实粉丝,并将所有部分提取到单独的列中:

if (!require("pacman")) install.packages("pacman")
pacman::p_load(dplyr, tidyr)

regx <- "(^[A-Za-z]+\\s+[0-9.a-z]+)\\s+([A-Z0-9]+)\\s*(.*)"

df %>%
    extract(model, c("a", "chassis", "b"), regx, remove=FALSE)

##                         model           a chassis           b    CRSP
## 1     Legacy 2.0  BG5 B4 AUTO  Legacy 2.0     BG5     B4 AUTO 3450000
## 2           Legacy 2.0 BH5 AT  Legacy 2.0     BH5          AT 3365000
## 3 Legacy 2.0i CVT Non Leather Legacy 2.0i     CVT Non Leather 4950000
## 4             Legacy 2.0i CVT Legacy 2.0i     CVT             5250000
## 5      Legacy 2.0 BL5 AUTO B4  Legacy 2.0     BL5     AUTO B4 4787526
## 6         Legacy 2.0 BP5 AUTO  Legacy 2.0     BP5        AUTO 3550000
## 7     Legacy 2.0 BM5 AUTO CVT  Legacy 2.0     BM5    AUTO CVT 5235000
Run Code Online (Sandbox Code Playgroud)

你可以用这个正则表达式更通用:

regx <- "(^[^ ]+\\s+[^ ]+)\\s+([^ ]+)\\s*(.*)"
Run Code Online (Sandbox Code Playgroud)

另请注意,您可以extract通过删除第一个和最后一个组的分组括号来使用以获取您所关注的列,如下所示:

regx <- "^[A-Za-z]+\\s+[0-9.a-z]+\\s+([A-Z0-9]+)\\s*.*"

df %>% 
    extract(model, "chassis", regx, remove=FALSE)
Run Code Online (Sandbox Code Playgroud)

  • 我在**dplyr**管道'%>%`内的同一数据帧上有其他先前和后续的数据操作步骤,所以这个解决方案更方便,因为我可以直接将它插入循环中.谢谢@TylerRinker (2认同)