require(microbenchmark)
require(tidyverse)
#Generate a random vector of 22-character long strings consisting of numeric characters
random_char_vec = sprintf("%022.0f", runif(1e7)*1e22)
#Put it into a tibble
random_num_tibble = tibble(random_char_vec = random_char_vec)
#The problem seems to be when the character string is very long;
#if each element of random_char_vec is only five characters
#this takes no time at all;
#at 22 digits it takes over two minutes.
microbenchmark(
{
factor_random_num = as.factor(random_char_vec)
},
times=1)
Unit: seconds
expr min lq mean
{ factor_random_num = as.factor(random_char_vec) } 146.2098 146.2098 146.2098
median uq max neval
146.2098 146.2098 146.2098 1
#This takes two seconds.
microbenchmark(
{
factor_random_num = factor(random_char_vec, levels = unique(random_char_vec))
},
times=1)
Unit: seconds
expr
{ factor_random_num = factor(random_char_vec, levels = unique(random_char_vec)) }
min lq mean median uq max neval
1.796813 1.796813 1.796813 1.796813 1.796813 1.796813 1
#The key to the speedup is precomputing the levels; without setting levels, no speedup.
microbenchmark(
{
factor_random_num = factor(random_char_vec)
},
times=1)
Unit: seconds
expr min lq mean median
{ factor_random_num = factor(random_char_vec) } 123.8821 123.8821 123.8821 123.8821
uq max neval
123.8821 123.8821 1
2条答案
按热度按时间mmvthczy1#
使用factor()函数和“levels”参数要快得多。使用“层次”论点是关键;没有它,factor()和.factor()一样慢。示例如下:
我不知道为什么在mutate()语句中调用factor()有时会导致如此缓慢的性能。
希望这对遇到同样问题的人有所帮助!
pn9klfpd2#
tl;dr基本函数通常可以通过执行更少的操作来加速,但通常不值得付出这种努力。
data.table
提供了as.factor
的替代方案。一般来说,如果函数体(
your_func
,在控制台中没有括号)没有像.Primitive
或.Internal
这样的内容,那么可能会有显著的速度提升。问题是,这值得努力吗?在我的机器上,一个基本情况,长度为1亿的200级因子,基本
as.factor
需要3秒。切换到
data.table
方法,使用(不可取的)包内部函数,这可以大致减半。除非经常运行,否则转换不值得花时间键入它。