我有一個字串向量
vec <- c("1ZQOYNBAA55", "2JSNHGKLRBB66", "3HVXCC77", "4LDD88", "5CIFMTLYXEE99")
> vec
[1] "1ZQOYNBAA55" "2JSNHGKLRBB66" "3HVXCC77" "4LDD88" "5CIFMTLYXEE99"
...我想從每個字串中獲取最后 3 個字符。要獲得前 3 個字符,我可以使用substr()
substr(vec,1,3)
我會認為substr()可能存在類似“fromLast”引數的東西
vec_ends <- substr(vec,1,3, fromLast = TRUE)
有預期的輸出
> vec_ends
[1] "A55" "B66" "C77" "D88" "E99"
但substr()只能以一種方式作業。在我的資料集中,字串長度是可變的,因此不能參考絕對字符數或字串長度,并且字串拆分沒有一致的分隔符分隔符。有誰知道在 R 中執行此操作的簡單方法?
uj5u.com熱心網友回復:
這是一種不使用正則運算式的方法(通常但并不總是意味著它更快)。
get_last_n_chars <- function(vec, n = 3) {
substr(vec, nchar(vec)-(n-1), nchar(vec))
}
get_last_n_chars(vec)
# [1] "A55" "B66" "C77" "D88" "E99"
基準測驗 - 只是為了好玩
通常(通常?!)性能是無關緊要的,您應該使用任何最清晰的代碼。
但是,我很感興趣,而且在這種情況下,避免使用正則運算式確實會更快。然而真正的大勝利不是使用sapply(strsplit())方法——我實際上不得不從情節中洗掉最后一點,因為它打破了規模。
input_vec <- c("1ZQOYNBAA55", "2JSNHGKLRBB66", "3HVXCC77", "4LDD88", "5CIFMTLYXEE99")
num_iterations <- c(10, 1e3, 1e4)
results <- bench::press(
rows = num_iterations,
{
vec <- rep(input_vec, rows)
bench::mark(
min_iterations = 100,
sub = {
sub(".*(.{3})$", "\\1", vec)
},
gsub = {
gsub(".*(.{3})$", "\\1", vec)
},
strsplit = {
sapply(strsplit(vec, split=""), function(x) paste(tail(x, 3), collapse = ""))
},
get_last_n_chars_fun = {
get_last_n_chars(vec)
},
stringi = {
out <- stringi::stri_reverse(vec)
out <- substr(out,1,3)
out <- stringi::stri_reverse(out)
out
}
)
}
)
結果圖:

輸出autoplot(results) theme_bw():

uj5u.com熱心網友回復:
您可以使用一種sub()方法:
vec_ends <- sub(".*(.{3})$", "\\1", vec)
vec_ends
[1] "A55" "B66" "C77" "D88" "E99"
uj5u.com熱心網友回復:
> gsub(".*(.{3})$", "\\1", vec)
[1] "A55" "B66" "C77" "D88" "E99"
這是不使用正則運算式的替代方法:
> sapply(strsplit(vec, split=""), function(x) paste(tail(x, 3), collapse = ""))
[1] "A55" "B66" "C77" "D88" "E99"
uj5u.com熱心網友回復:
我也找到了這個包stringi,可以重復使用stri_reverse()。
library(stringi)
out <- stri_reverse(vec)
out <- substr(out,1,3)
out <- stri_reverse(out)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/520236.html
標籤:r细绳
