从 data.frame 的列中提取单词

Extract words from a column of data.frame

在我的数据中,有一列像:

df <- data.frame(status = c("GET/sfuksd1567","GET/sjsh787","POST/hsfhuks","GET/sfukfiezd17","POST/fshks"), stringsAsFactors = FALSE)

我想自动创建另一列,它是变量状态的指示符,它只提取 "GET" 或 "POST",如 df$ind=c("GET","GET","POST","GET","POST")

我已经尝试了 substr 功能,但我没有成功。

原始数据:

> df
           status
1  GET/sfuksd1567
2     GET/sjsh787
3    POST/hsfhuks
4 GET/sfukfiezd17
5      POST/fshks

预期结果:

> df
           status  ind
1  GET/sfuksd1567  GET
2     GET/sjsh787  GET
3    POST/hsfhuks POST
4 GET/sfukfiezd17  GET
5      POST/fshks POST

我们有:

df<-data.frame(status=c("GET/sfuksd1567","GET/sjsh787","POST/hsfhuks","GET/sfukfiezd17","POST/fshks"),stringsAsFactors=F)

你可以做到:

df$ind<-sapply(1:nrow(df),function(x){strsplit(df$status,'/')[[x]][1]})

df$ind<-sapply(strsplit(df$status,'/'),`[[`,1)

两者都return

df
           status  ind
1  GET/sfuksd1567  GET
2     GET/sjsh787  GET
3    POST/hsfhuks POST
4 GET/sfukfiezd17  GET
5      POST/fshks POST

基准:

microbenchmark(david=sub("/.*", "", df$status),etienne=sapply(strsplit(df$status,'/'),`[[`,1))

Unit: microseconds
    expr    min      lq     mean  median     uq     max neval cld
   david 25.198 25.8985 27.64456 26.5980 27.298 116.189   100  a 
 etienne 62.294 63.3440 65.13979 63.8695 65.094 128.088   100   b

您可以使用正则表达式删除反斜杠后的所有内容

df$ind <- sub("/.*", "", df$status)
df
#            status  ind
# 1  GET/sfuksd1567  GET
# 2     GET/sjsh787  GET
# 3    POST/hsfhuks POST
# 4 GET/sfukfiezd17  GET
# 5      POST/fshks POST

或者如果你不喜欢正则表达式,你可以试试

library(tidyr)
separate(df, "status", c("ind", "status"))

library(data.table) ## V1.9.6+
setDT(df)[, tstrsplit(status, "/")]

read.table(text = df$status, sep = "/")

最后三个选项只会将 status 列拆分为两个单独的列。

我们可以使用 stri_extract_first_words 来自 library(stringi)

library(stringi)
stri_extract_first_words(df$status)
#[1] "GET"  "GET"  "POST" "GET"  "POST"

tidyr 的另一个选项是 extract

extract(df, status, into='ind', '([^/]+)/.*', remove=FALSE)

基准

使用 stri_extract_first_words,基准是:

david <- function() sub('/.*', '', df$status)
etienne <- function() sapply(strsplit(df$status,'/'),`[[`,1)
akrun <- function()stri_extract_first_words(df$status)
df <-  df[sample(1:nrow(df), 1e6, replace=TRUE),, drop=FALSE]
library(microbenchmark)
microbenchmark(david(), etienne(), akrun(), unit='relative', times=20L)
#Unit: relative
#      expr      min       lq     mean   median       uq      max neval
#   david() 1.826192 1.824263 1.781562 1.814156 1.788085 1.699008    20
# etienne() 4.935629 5.159218 5.136180 5.198875 5.137107 5.930806    20
#   akrun() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    20

注意:@David Arenburg 的 post 中还有其他选项。我猜 sub 版本会更快。我可能是错的。