stringi
パッケージを使用して、別の解決策。これまでに提案されているすべてのソリューションを比較するベンチマークを確認します。 stringi
はベースRよりもわずかに速いですが、単純な解決策を探すならば、もちろんもう少し複雑です。したがって、あなたのスピードやシンプルさに応じてどちらかが良いです。しかし、stringiはより複雑なケースに対して柔軟性を提供します。 (私たちはすべてのdata.frame
を設定し、型を変換するためのslighlty異なるアプローチを使用していたので、ベンチマークは完全に同等ではありませんが、注意してください。)
UPDATE:私は私の答えにコードを更新したRui Barradasのコメントを受けて 。 (i)カラムの数値への変換を含むstringi
のアプローチを使用して関数を提案しました。 (ii)さらに、ベンチマークを追加して、これまでに提案されているすべてのアプローチ(コメントにも)が含まれるようにしました。公正な比較の半分を達成するために、私は提案されたアプローチを修正したので、出力は同じです。特に、比較のために列の数値への変換をスキップして、暫定的な代入などを避けてコマンドを同様に簡潔にしました。stringi
はまだまだ最速です。
公平な比較に関して何かを監督している場合は、私を修正してください(特にstringr
解決策はコード通りに改善されるかもしれませんが、私はパッケージに慣れていないので、提案された解決策を維持しました)。
library(stringi)
library(stringr)
library(microbenchmark)
strings <- c("rfoutputtablep7q10000t20000c100",
"rfoutputtablep7q1000t20000c100",
"svmLinear2outputtablep7q20000t20000c100",
"svmLinear2outputtablep7q5000t20000c100")
split_to_df <- function(string, splititems, colidschar, firstcolname, replsplit_tonames) {
data <- as.data.frame(do.call(rbind
,stri_split_regex(strings, paste(splititems, collapse = "|")))
,stringsAsFactors = FALSE)
names(data) <- c(firstcolname, stri_replace_all_regex(splititems, replsplit_tonames, ""))
numericcols <- setdiff(1:ncol(data), colidschar)
data[,numericcols] <- lapply(data[,numericcols], as.numeric)
return(data)
}
stringi_approach_complete <- function() {
df <- split_to_df(string = strings
,splititems = c("outputtablep(?=\\d)", "q(?=\\d)", "t(?=\\d)", "c(?=\\d)")
,colidschar = 1
,firstcolname = "A"
,replsplit_tonames = "\\(.*\\)|outputtable")
# class(df$p)
# [1] "numeric"
# A p q t c
# 1 rf 7 10000 20000 100
# 2 rf 7 1000 20000 100
# 3 svmLinear2 7 20000 20000 100
# 4 svmLinear2 7 5000 20000 100
}
stringi_approach_compare <- function() {
data <- as.data.frame(do.call(rbind, stri_split_regex(strings, c("outputtable|p(?=\\d)|q(?=\\d)|t(?=\\d)|c(?=\\d)"))))
names(data) <- c("A", "p", "q", "t", "c")
#class(data$p)
#[1] "factor"
#data
# A p q t c
# 1 rf 7 10000 20000 100
# 2 rf 7 1000 20000 100
# 3 svmLinear2 7 20000 20000 100
# 4 svmLinear2 7 5000 20000 100
}
stringr_approach <- function() {
res <- data.frame(p = str_extract(str_extract(strings, "p\\d+"), "\\d+"),
q = str_extract(str_extract(strings, "q\\d+"), "\\d+"),
t = str_extract(str_extract(strings, "t\\d+"), "\\d+"),
c = str_extract(str_extract(strings, "c\\d+"), "\\d+"))
#class(res$p)
#[1] "factor"
#res
# p q t c
# 1 7 10000 20000 100
# 2 7 1000 20000 100
# 3 7 20000 20000 100
# 4 7 5000 20000 100
}
base_approach1 <- function() {
res <- do.call(rbind, strsplit(strings, 'outputtable|p|q|t|c'))
res <- as.data.frame(res[, -2])
names(res) <- c("A", "p", "q", "t", "c")
#class(res$p)
#[1] "factor"
#res[-1] <- lapply(res[-1], function(x) as.numeric(as.character(x)))
#res
# A p q t c
#1 rf 7 10000 20000 100
#2 rf 7 1000 20000 100
#3 svmLinear2 7 20000 20000 100
#4 svmLinear2 7 5000 20000 100
}
base_approach2 <- function() {
df <- setNames(data.frame(do.call(rbind, strsplit(strings, 'outputtable\\D|p|q|t|c'))), c("A", "p", "q", "t", "c"))
#class(df$p)
#[1] "factor"
#df
# A p q t c
# 1 rf 7 10000 20000 100
# 2 rf 7 1000 20000 100
# 3 svmLinear2 7 20000 20000 100
# 4 svmLinear2 7 5000 20000 100
}
microbenchmark(
base_approach1(),
base_approach2(),
stringi_approach_compare(),
stringr_approach(),
stringi_approach_complete()
)
# Unit: microseconds
# expr min lq mean median uq max neval
# base_approach1() 260.139 273.3635 337.1985 285.6005 298.2330 5280.152 100
# base_approach2() 352.906 362.1820 461.8205 374.8140 391.9850 4645.791 100
# stringi_approach_compare() 280.667 297.8380 312.8426 307.3125 319.1545 654.098 100
# stringr_approach() 849.499 867.6570 956.7596 886.2100 923.7115 5651.609 100
# stringi_approach_complete() 319.747 333.9580 461.5521 346.7870 369.0900 10985.052 100
'' 'tidyr :: separate'''を数回使用してください。 – rsmith54
正規表現を使用できます。 – kurdy
正規表現は私を混乱させるものです。あなたが私を助けてくれたら、本当に感謝します。私はまだ非常に初心者です:( –