在我的数据中,有一个列如下:
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
答案 0 :(得分:10)
您可以使用正则表达式删除反斜杠后的所有内容
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
列拆分为两个独立的列。
答案 1 :(得分:3)
我们有:
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)
两者都返回
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
答案 2 :(得分:2)
我们可以使用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的帖子中还有其他选项。我猜测sub
版本更快。我错了。