我在R中使用以下代码:
df$max_col<- sapply(df$col, function(x) ifelse(x == "", 0, strsplit(as.character(x), "", perl = TRUE)[[1]] %>% as.numeric %>% max(na.rm = T)))
此代码基本上会打断类似“ 123456”的字符串,并将其转换为数字并从中返回最大值。现在,我有一列满是这样的字符串,并且这段代码可以很好地运行,直到数据量很小为止。但是,当数据大小为2500万行(我目前正在处理)时,此代码将变得非常慢。这段代码是否还有其他选择,可以通过它从存储在新列中的字符串中获取最大值?
答案 0 :(得分:2)
基于我上面的评论的答案(但我已经修改了代码,使其可以实际使用):
x <- c("123", "224", "221", "1912323", "445")
apply(sapply(1:9, function(p) grepl(p, x)), 1, function(k) max(which(k)))
# the above will work if 0 is never the largest number in any cell
更通用的版本:
doit <- function(x) apply(sapply(0:9, function(p) grepl(p, x)), 1, function(k) max(which(k)))-1
x <- c("123", "224", "221", "1912323", "445", "000")
doit(x)
# [1] 3 4 2 9 5 0
这比使用strsplit的原始代码快3倍...但是我敢肯定还有改进的余地。嗯...实际上,我将再次尝试使用strsplit
:
doit3 <- function(.) sapply(strsplit(.,""), max)
doit3(x)
# [1] "3" "4" "2" "9" "5" "0"
这比我以前的方法快5倍。因此,问题不在sapply
或strsplit
中,而在其他组件中。如果需要将其转换为数字,请在外层添加as.numeric
,这不会花费太多时间:
doit4 <- function(.) as.numeric(sapply(strsplit(.,""), max))
> doit4(x)
# [1] 3 4 2 9 5 0
答案 1 :(得分:1)
对于25,000,000长度的矢量,转换为整数然后使用%%
和%/%
计算数字似乎最快:
a <- as.character(sample(1:1e6, size = 25e6, replace = TRUE))
use_grepl <- function(x) {
o <- integer(length(x))
o[grep('1', x, fixed = TRUE)] <- 1L
o[grep('2', x, fixed = TRUE)] <- 2L
o[grep('3', x, fixed = TRUE)] <- 3L
o[grep('4', x, fixed = TRUE)] <- 4L
o[grep('5', x, fixed = TRUE)] <- 5L
o[grep('6', x, fixed = TRUE)] <- 6L
o[grep('7', x, fixed = TRUE)] <- 7L
o[grep('8', x, fixed = TRUE)] <- 8L
o[grep('9', x, fixed = TRUE)] <- 9L
o
}
use_strsplit <- function(x) {
tbl19 <- as.character(1:9)
vapply(strsplit(x, split = "", fixed = TRUE),
function(v) {
max(fmatch(v, table = tbl19, nomatch = 0L))
},
0L)
}
use_mod <- function(xx) {
nth_digit_of <- function (x, n) {
{x %% 10^n} %/% 10^{n - 1L}
}
v <- as.integer(xx)
most_digits <- as.integer(ceiling(log10(max(v))) + 1)
o <- nth_digit_of(v, 1L)
for (vj in 2:most_digits) {
o <- pmax.int(o, nth_digit_of(v, vj))
}
as.integer(o)
}
doit4 <- function(V) as.numeric(sapply(strsplit(V, ""), max))
bench::mark(use_mod(a), use_grepl(a), doit4(a))
# A tibble: 3 x 14
expression min mean median max `itr/sec` mem_alloc n_gc n_itr total_time result memory time
<chr> <bch> <bch> <bch:> <bch> <dbl> <bch:byt> <dbl> <int> <bch:tm> <list> <list> <lis>
1 use_mod(a) 14.4s 14.4s 14.4s 14.4s 0.0693 2.61GB 3 1 14.4s <int ~ <Rpro~ <bch~
2 use_grepl~ 38.2s 38.2s 38.2s 38.2s 0.0262 1.32GB 0 1 38.2s <int ~ <Rpro~ <bch~
3 doit4(a) 56.5s 56.5s 56.5s 56.5s 0.0177 1.18GB 7 1 56.5s <dbl ~ <Rpro~ <bch~