今天要解决一个长期困扰我的问题:使用strsplit或stringr::str_split,都是将元素分拆为列表的形式,虽然这样的通用性比较好,但是在大多数情形下,分拆元素的个数是固定的,更希望以数据框的形式返回,这样更具有通用性。
例如
strsplit(jd201610$date,"-") %>% head(3)
## [[1]]
## [1] "19" "9月 " "16"
##
## [[2]]
## [1] "19" "9月 " "16"
##
## [[3]]
## [1] "19" "9月 " "16"
str_split(jd201610$date,"-") %>% head(3)
## [[1]]
## [1] "19" "9月 " "16"
##
## [[2]]
## [1] "19" "9月 " "16"
##
## [[3]]
## [1] "19" "9月 " "16"
思路一:强制转换数据框再转置
一种思路是简单暴力的,强制转化为数据框。但由于as.data.frame是按元素转到数据框的列,不是想要的结果,所以还多了个转置的步骤,这样就大大增加了运行时间。
str_split_todf01 <- function(strvec,sep){
tep <- strsplit(strvec,sep)
df <- as.data.frame(tep)
df <- t(df)
rownames(df) <- 1:nrow(df)
return(df)
}
str_split_todf01(jd201610$date,"-") %>% head(10)
## [,1] [,2] [,3]
## 1 "19" "9月 " "16"
## 2 "19" "9月 " "16"
## 3 "19" "9月 " "16"
## 4 "19" "9月 " "16"
## 5 "19" "9月 " "16"
## 6 "19" "9月 " "16"
## 7 "19" "9月 " "16"
## 8 "19" "9月 " "16"
## 9 "19" "9月 " "16"
## 10 "19" "9月 " "16"
system.time(str_split_todf01(jd201610$date,"-"))
## 用户 系统 流逝
## 27.97 0.03 28.11
思路二:先转矩阵再转数据框
str_split_todf02 <- function(strvec,sep){
tep <- strsplit(strvec,sep)
len <- length(tep[[1]])
return(as.data.frame(matrix(unlist(tep),ncol=len,byrow = T)))
}
str_split_todf02(jd201610$date,sep="-") %>% head(10)
## V1 V2 V3
## 1 19 9月 16
## 2 19 9月 16
## 3 19 9月 16
## 4 19 9月 16
## 5 19 9月 16
## 6 19 9月 16
## 7 19 9月 16
## 8 19 9月 16
## 9 19 9月 16
## 10 19 9月 16
system.time(str_split_todf02(jd201610$date,sep="-"))
## 用户 系统 流逝
## 0.50 0.00 0.49
思路三:用lapply提取列表元素构成数据框
str_split_todf03 <- function(strvec,sep){
tep <- strsplit(strvec,sep)
li <- list()
len <- length(tep[[1]])
for(i in 1:len){
li[[i]] <- sapply(tep, `[`, i)
}
names(li) <- 1:len
return(data.frame(li))
}
str_split_todf03(jd201610$date,"-") %>% head(10)
## X1 X2 X3
## 1 19 9月 16
## 2 19 9月 16
## 3 19 9月 16
## 4 19 9月 16
## 5 19 9月 16
## 6 19 9月 16
## 7 19 9月 16
## 8 19 9月 16
## 9 19 9月 16
## 10 19 9月 16
system.time(str_split_todf03(jd201610$date,"-"))
## 用户 系统 流逝
## 0.72 0.00 0.72
结论
由运行时间,思路一最不可取,思路二和三效率差不多。思路三多了个循环,美感稍差一些。
得到经验:由列表转数据框时,如果行列不是想要的形式,可以先换成矩阵,再换成数据框;而不是使用数据框转置。