<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/read-the-docs-before-questioning-rs-defaults/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.enchufa2.es/archives/read-the-docs-before-questioning-rs-defaults.html"> R � Enchufa2</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>The latest <em>R tip</em> in <em>Win-Vector Blog</em> encourages you to <a rel="nofollow" href="http://www.win-vector.com/blog/2018/08/r-tip-use-radix-sort/" target="_blank"><em>Use Radix Sort</em></a> based on a simple benchmark showing a x35 speedup compared to the default method, but with no further explanation. In my opinion, though, the <em>complete</em> tip would be, instead, <em>use radix sort… <strong>if you know what you are doing</strong></em>, because a quick benchmark shouldn't spare you the effort of actually reading the docs. And here is a spoiler: <em>you are already using it</em>.</p>
<p>One may wonder why R's default sorting algorithm is so bad, and why was even chosen. The thing is that there is a trick here, and to understand it, first we must understand the benchmark's data and then read the docs. This is the function from the <a rel="nofollow" href="https://github.com/WinVector/rqdatatable/blob/master/extras/radix_timing.md" target="_blank">original code</a> (slightly modified for subsequent reuse) that generates the data:</p>
<pre><code>mk_data &lt;- <span>function</span>(nrow, stringsAsFactors = <span>FALSE</span>) {
  alphabet &lt;- paste(<span>&quot;sym&quot;</span>, seq_len(max(<span>2</span>, floor(nrow^(<span>1</span>/<span>3</span>)))), sep = <span>&quot;_&quot;</span>)
  data.frame(col_a = sample(alphabet, nrow, replace=<span>TRUE</span>),
             col_b = sample(alphabet, nrow, replace=<span>TRUE</span>),
             col_c = sample(alphabet, nrow, replace=<span>TRUE</span>),
             col_x = runif(nrow),
             stringsAsFactors = stringsAsFactors)
}

set.seed(<span>32523</span>)
d &lt;- mk_data(<span>1e+6</span>)

summary(d)</code></pre>
<pre><code>##     col_a              col_b              col_c          
##  Length:1000000     Length:1000000     Length:1000000    
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
##                                                          
##      col_x          
##  Min.   :0.0000002  
##  1st Qu.:0.2496717  
##  Median :0.4991010  
##  Mean   :0.4996031  
##  3rd Qu.:0.7494089  
##  Max.   :0.9999999</code></pre>
<pre><code>length(table(d$col_a))</code></pre>
<pre><code>## [1] 99</code></pre>
<p>There are three character columns sampled from 99 symbols (<code>sym_1</code>, <code>sym_2</code>, …, <code>sym_99</code>) and a numeric column sampled from a uniform. The first three columns are thus clearly factors, but they are not treated as such. Let's see now what <code>help(sort)</code> has to tell us about the sorting method, which by default is <code>method=&quot;auto&quot;</code>:</p>
<blockquote>
<p>The &quot;auto�? method selects &quot;radix�? for short (less than 2^31 elements) numeric vectors, integer vectors, logical vectors and factors; otherwise, &quot;shell�?.</p>
</blockquote>
<p>So, as I said in the opening paragraph, you are <em>already</em> using radix sort, except for characters. Let's see then what happens if we treat such columns as proper factors:</p>
<pre><code><span>library</span>(microbenchmark)

set.seed(<span>32523</span>)
d &lt;- mk_data(<span>1e+6</span>, stringsAsFactors = <span>TRUE</span>)

timings &lt;- microbenchmark(
  order_default = d[order(d$col_a, d$col_b, d$col_c, d$col_x), , 
                    drop = <span>FALSE</span>],
  order_radix = d[order(d$col_a, d$col_b, d$col_c, d$col_x,
                        method = <span>&quot;radix&quot;</span>), ,
                  drop = <span>FALSE</span>],
  times = <span>10L</span>)

print(timings)</code></pre>
<pre><code>## Unit: milliseconds
##           expr      min       lq     mean   median       uq      max neval
##  order_default 289.4685 312.0257 388.5259 387.8308 418.2673 584.4771    10
##    order_radix 265.6491 321.8337 421.2072 376.1166 512.0047 667.0545    10
##  cld
##    a
##    a</code></pre>
<p>Unsurprisingly, timings are the same, because R automatically selects <code>&quot;radix&quot;</code> for you when appropriate. But when is it considered appropriate and why isn't it appropriate <em>in general</em> for character vectors? We should go back to the docs:</p>
<blockquote>
<p>The implementation is orders of magnitude faster than shell sort for character vectors, in part thanks to clever use of the internal CHARSXP table.</p>
<p>However, there are some caveats with the radix sort:</p>
<ul>
<li>If x is a character vector, all elements must share the same encoding. Only UTF-8 (including ASCII) and Latin-1 encodings are supported. Collation always follows the &quot;C�? locale.</li>
<li>Long vectors (with more than 2^32 elements) and complex vectors are not supported yet.</li>
</ul>
</blockquote>
<p>An there it is: R is doing the right thing for you for the general case. So let us round up the tip: <em>enforce <code>method=&quot;radix&quot;</code> for character vectors if you know what you are doing</em>. And, please, do read the docs.</p>
<p><em>Article originally published in Enchufa2.es: <a rel="nofollow" href="https://www.enchufa2.es/archives/read-the-docs-before-questioning-rs-defaults.html" target="_blank">Read the docs before questioning R’s defaults</a></em>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://www.enchufa2.es/archives/read-the-docs-before-questioning-rs-defaults.html"> R � Enchufa2</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/s_zk04ilXEo" height="1"></a></div>