<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/"></div></div><div><a data-url="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/" data-counturl="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/" data-count="horizontal" data-text="Fast and Big Linear Model Fitting with bigmemory and RcppEigen" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://casualinference.org/2016/07/07/big_fast_lm/"> jared huling</a></strong>, and kindly contributed to <a rel="nofollow" href="http://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>In a previous <a target="_blank" href="http://casualinference.org/2016/06/04/bigmemory_rcppeigen/">post</a>, I went over the basics of linking up <a target="_blank" href="http://casualinference.org/2016/07/07/big_fast_lm/www.bigmemory.org">bigmemory</a> and the <a target="_blank" href="http://eigen.tuxfamily.org/index.php?title=Main_Page">eigen</a> C++ library via <a target="_blank" href="http://cran.r-project.org/web/packages/RcppEigen/index.html">RcppEigen</a>. In this post I’ll take this a bit further by creating a version of the <code>fastLm()</code> function of RcppEigen that can accept bigmemory objects. By doing so, we will create a fast way to fit linear models using data which is too big to fit in RAM. With RcppEigen, fitting linear models using out-of-memory computation doesn’t have to be slow. The code for this is all on github in the <a target="_blank" href="https://github.com/jaredhuling/bigFastlm">bigFastlm</a> package.</p>
<p>Before we even start, most of the work is already done as we’ll just need to change a few lines of the core C++ code of the <code>fastLm()</code> function so that it we can map the bigmemory pointer to data on disk to an eigen matrix object.</p>
<p>The core code of <code>fastLm</code> can be found <a target="_blank" href="https://github.com/RcppCore/RcppEigen/tree/master/src">here</a>. The data object which is being loaded into C++ from R is mapped to an eigen matrix object at line 208 of <code>fastLm.cpp</code>.</p>
<figure>
<pre><code data-lang="cpp"><span>const</span> <span>Map</span><span>&lt;</span><span>MatrixXd</span><span>></span>  <span>X</span><span>(</span><span>as</span><span>&lt;</span><span>Map</span><span>&lt;</span><span>MatrixXd</span><span>></span> <span>></span><span>(</span><span>Xs</span><span>));</span></code></pre>
</figure>
<p>We need to change the above code to</p>
<figure>
<pre><code data-lang="cpp"><span>XPtr</span><span>&lt;</span><span>BigMatrix</span><span>></span> <span>bMPtr</span><span>(</span><span>Xs</span><span>);</span>

<span>unsigned</span> <span>int</span> <span>typedata</span> <span>=</span> <span>bMPtr</span><span>-></span><span>matrix_type</span><span>();</span>

<span>if</span> <span>(</span><span>typedata</span> <span>!=</span> <span>8</span><span>)</span>
<span>{</span>
  <span>throw</span> <span>Rcpp</span><span>::</span><span>exception</span><span>(</span><span>&quot;type for provided big.matrix not available&quot;</span><span>);</span>
<span>}</span>

<span>const</span> <span>Map</span><span>&lt;</span><span>MatrixXd</span><span>></span>  <span>X</span> <span>=</span> <span>Map</span><span>&lt;</span><span>MatrixXd</span><span>></span><span>((</span><span>double</span> <span>*</span><span>)</span><span>bMPtr</span><span>-></span><span>matrix</span><span>(),</span> <span>bMPtr</span><span>-></span><span>nrow</span><span>(),</span> <span>bMPtr</span><span>-></span><span>ncol</span><span>()</span>  <span>);</span></code></pre>
</figure>
<p>The above modification first takes Xs as an <a target="_blank" href="http://www.r-bloggers.com/external-pointers-with-rcpp/">Rcpp external pointer object</a> (<code>XPtr</code>) and then checks to make sure it’s a double type (for now I’m ignoring all other data types (int, etc) for simplicity). Now that X is a mapped eigen matix object which points to data on disk, what else do we need to do? Well, not much! We just need to make sure that the correct object types are defined for the R-callable function. To do this, we need to change</p>
<figure>
<pre><code data-lang="cpp"><span>// [[Rcpp::export]]
</span><span>Rcpp</span><span>::</span><span>List</span> <span>fastLm_Impl</span><span>(</span><span>Rcpp</span><span>::</span><span>NumericMatrix</span> <span>X</span><span>,</span> <span>Rcpp</span><span>::</span><span>NumericVector</span> <span>y</span><span>,</span> <span>int</span> <span>type</span><span>)</span> <span>{</span>
    <span>return</span> <span>lmsol</span><span>::</span><span>fastLm</span><span>(</span><span>X</span><span>,</span> <span>y</span><span>,</span> <span>type</span><span>);</span> 
<span>}</span></code></pre>
</figure>
<p>To</p>
<figure>
<pre><code data-lang="cpp"><span>// [[Rcpp::export]]
</span><span>RcppExport</span> <span>SEXP</span> <span>bigLm_Impl</span><span>(</span><span>SEXP</span> <span>X</span><span>,</span> <span>SEXP</span> <span>y</span><span>,</span> <span>SEXP</span> <span>type</span><span>)</span>
<span>{</span>
  <span>BEGIN_RCPP</span>
  <span>Rcpp</span><span>::</span><span>RObject</span> <span>__result</span><span>;</span>
  <span>Rcpp</span><span>::</span><span>RNGScope</span> <span>__rngScope</span><span>;</span>
  <span>Rcpp</span><span>::</span><span>traits</span><span>::</span><span>input_parameter</span><span>&lt;</span> <span>Rcpp</span><span>::</span><span>XPtr</span><span>&lt;</span><span>BigMatrix</span><span>></span> <span>>::</span><span>type</span> <span>X_</span><span>(</span><span>X</span><span>);</span>
  <span>Rcpp</span><span>::</span><span>traits</span><span>::</span><span>input_parameter</span><span>&lt;</span> <span>Rcpp</span><span>::</span><span>NumericVector</span> <span>>::</span><span>type</span> <span>y_</span><span>(</span><span>y</span><span>);</span>
  <span>Rcpp</span><span>::</span><span>traits</span><span>::</span><span>input_parameter</span><span>&lt;</span> <span>int</span> <span>>::</span><span>type</span> <span>type_</span><span>(</span><span>type</span><span>);</span>
  <span>__result</span> <span>=</span> <span>Rcpp</span><span>::</span><span>wrap</span><span>(</span><span>lmsol</span><span>::</span><span>fastLm</span><span>(</span><span>X_</span><span>,</span> <span>y_</span><span>,</span> <span>type_</span><span>));</span>
  <span>return</span> <span>__result</span><span>;</span>
  <span>END_RCPP</span>
<span>}</span></code></pre>
</figure>
<p>in<code>fastLm.cpp</code>. <code>// [[Rcpp::export]]</code> had some trouble doing this automatically, so the above is just what that <em>should</em> have created.</p>
<p>So now with the proper R functions to call this, we’re basically done. I had to create a few utility functions to make everything work nicely, but the main work is just the above.</p>
<p>One important detail: for now, we can only use the LLT and LDLT methods for computation, as the other decompositions create objects which scale with the size of the data, so for now I’m ignoring the more robust decompositions like QR. Perhaps someone else can figure out how to perform these in a memory-conscious manner.</p>
<h3>Comparison with biglm</h3>
<p>Now we’ll run a (perhaps not-so-fair) comparison with the <code>biglm</code> function of <a target="_blank" href="https://cran.r-project.org/web/packages/biglm/index.html">biglm</a>. Specifically, we’ll use the <code>biglm.big.matrix</code> function provided by the <a target="_blank" href="https://cran.r-project.org/web/packages/biganalytics/index.html">biganalytics</a> which interfaces bigmemory and biglm. The following code creates a bigmemory object on disk (actually, two because biglm requires the matrix object to contain the response, whereas bigFastlm requires that the response be an R vector. It’s hard to say which is a better design choice, but I’m sticking with the approach which doesn’t allow an R formula expression).</p>
<figure>
<pre><code data-lang="r"><span>suppressMessages</span><span>(</span><span>library</span><span>(</span><span>bigmemory</span><span>))</span><span>
</span><span>suppressMessages</span><span>(</span><span>library</span><span>(</span><span>biganalytics</span><span>))</span><span>
</span><span>suppressMessages</span><span>(</span><span>library</span><span>(</span><span>bigFastlm</span><span>))</span><span>
</span><span>nrows</span><span> </span><span>&lt;-</span><span> </span><span>1000000</span><span>
</span><span>ncols</span><span> </span><span>&lt;-</span><span> </span><span>100</span><span>
</span><span>bkFile</span><span> </span><span>&lt;-</span><span> </span><span>&quot;big_matrix.bk&quot;</span><span>
</span><span>descFile</span><span> </span><span>&lt;-</span><span> </span><span>&quot;big_matrix.desc&quot;</span><span>
</span><span>big_mat</span><span> </span><span>&lt;-</span><span> </span><span>filebacked.big.matrix</span><span>(</span><span>nrow</span><span> </span><span>=</span><span> </span><span>nrows</span><span>,</span><span> </span><span>ncol</span><span> </span><span>=</span><span> </span><span>ncols</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;double&quot;</span><span>,</span><span> </span><span>backingfile</span><span> </span><span>=</span><span> </span><span>bkFile</span><span>,</span><span> </span><span>backingpath</span><span> </span><span>=</span><span> </span><span>&quot;.&quot;</span><span>,</span><span> </span><span>descriptorfile</span><span> </span><span>=</span><span> </span><span>descFile</span><span>,</span><span>
</span><span>dimnames</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>NULL</span><span>,</span><span> </span><span>NULL</span><span>))</span><span>
</span><span>set.seed</span><span>(</span><span>123</span><span>)</span><span>
</span><span>for</span><span> </span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>ncols</span><span>)</span><span> </span><span>big_mat</span><span>[,</span><span> </span><span>i</span><span>]</span><span> </span><span>=</span><span> </span><span>rnorm</span><span>(</span><span>nrows</span><span>,</span><span> </span><span>mean</span><span> </span><span>=</span><span> </span><span>1</span><span>/</span><span>sqrt</span><span>(</span><span>i</span><span>))</span><span> </span><span>*</span><span> </span><span>i</span><span>
</span><span>bkFile</span><span> </span><span>&lt;-</span><span> </span><span>&quot;big_matrix2.bk&quot;</span><span>
</span><span>descFile</span><span> </span><span>&lt;-</span><span> </span><span>&quot;big_matrix2.desc&quot;</span><span>
</span><span>big_mat2</span><span> </span><span>&lt;-</span><span> </span><span>filebacked.big.matrix</span><span>(</span><span>nrow</span><span> </span><span>=</span><span> </span><span>nrows</span><span>,</span><span> </span><span>ncol</span><span> </span><span>=</span><span> </span><span>ncols</span><span> </span><span>+</span><span> </span><span>1</span><span>,</span><span> </span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;double&quot;</span><span>,</span><span> </span><span>backingfile</span><span> </span><span>=</span><span> </span><span>bkFile</span><span>,</span><span> </span><span>backingpath</span><span> </span><span>=</span><span> </span><span>&quot;.&quot;</span><span>,</span><span> </span><span>descriptorfile</span><span> </span><span>=</span><span> </span><span>descFile</span><span>,</span><span>
</span><span>dimnames</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>NULL</span><span>,</span><span> </span><span>NULL</span><span>))</span><span>
</span><span>for</span><span> </span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>ncols</span><span>)</span><span> </span><span>big_mat2</span><span>[,</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>1</span><span>]</span><span> </span><span>=</span><span> </span><span>big_mat</span><span>[,</span><span> </span><span>i</span><span>]</span><span>
</span><span>y</span><span> </span><span>&lt;-</span><span> </span><span>rnorm</span><span>(</span><span>nrows</span><span>)</span><span>
</span><span>big_mat2</span><span>[,</span><span>1</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>y</span><span>
</span><span>options</span><span>(</span><span>bigmemory.allow.dimnames</span><span>=</span><span>TRUE</span><span>)</span><span>
</span><span>colnames</span><span>(</span><span>big_mat2</span><span>)</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;y&quot;</span><span>,</span><span> </span><span>paste0</span><span>(</span><span>&quot;V&quot;</span><span>,</span><span> </span><span>1</span><span>:</span><span>ncols</span><span>))</span><span>
</span><span>options</span><span>(</span><span>bigmemory.allow.dimnames</span><span>=</span><span>FALSE</span><span>)</span><span>
</span><span>## create formula for biglm
</span><span>form</span><span> </span><span>&lt;-</span><span> </span><span>as.formula</span><span>(</span><span>paste</span><span>(</span><span>&quot;y ~ -1 +&quot;</span><span>,</span><span> </span><span>paste</span><span>(</span><span>paste0</span><span>(</span><span>&quot;V&quot;</span><span>,</span><span> </span><span>1</span><span>:</span><span>ncols</span><span>),</span><span> </span><span>collapse</span><span> </span><span>=</span><span> </span><span>&quot;+&quot;</span><span>)))</span></code></pre>
</figure>
<p>Now let’s see how <code>biglm</code> and <code>bigLm</code> (eigen + bigmemory) stack up. Note that this is an unfair comparison because <code>biglm</code> requires a formula argument and <code>bigLm</code> assumes you’re passing in a design matrix already and biglm uses the QR decomposition, which is slower than LLT or LDLT.</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>microbenchmark</span><span>)</span><span>
</span><span>res</span><span> </span><span>&lt;-</span><span> </span><span>microbenchmark</span><span>(</span><span>biglm.obj</span><span> </span><span>&lt;-</span><span> </span><span>biglm.big.matrix</span><span>(</span><span>form</span><span>,</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>big_mat2</span><span>),</span><span> </span><span>bigLm.obj</span><span> </span><span>&lt;-</span><span> </span><span>bigLm</span><span>(</span><span>big_mat</span><span>,</span><span> </span><span>y</span><span>),</span><span> </span><span>bigLm.obj2</span><span> </span><span>&lt;-</span><span> </span><span>bigLmPure</span><span>(</span><span>big_mat</span><span>,</span><span> </span><span>y</span><span>),</span><span> </span><span>## a slightly faster version that doesn't check for intercept
</span><span> </span><span>times</span><span> </span><span>=</span><span> </span><span>10L</span><span>)</span><span>
</span><span>print</span><span>(</span><span>summary</span><span>(</span><span>res</span><span>)[,</span><span>1</span><span>:</span><span>7</span><span>],</span><span> </span><span>digits</span><span> </span><span>=</span><span> </span><span>4</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##                                                   expr    min     lq
## 1 biglm.obj &lt;- biglm.big.matrix(form, data = big_mat2) 20.408 21.979
## 2                       bigLm.obj &lt;- bigLm(big_mat, y)  1.720  1.769
## 3                  bigLm.obj2 &lt;- bigLmPure(big_mat, y)  1.624  1.631
##     mean median     uq    max
## 1 22.987 22.788 23.981 25.995
## 2  1.825  1.793  1.867  2.055
## 3  1.673  1.669  1.693  1.741</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>max</span><span>(</span><span>abs</span><span>(</span><span>coef</span><span>(</span><span>biglm.obj</span><span>)</span><span> </span><span>-</span><span> </span><span>coef</span><span>(</span><span>bigLm.obj</span><span>)))</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 5.551115e-17</code></pre>
</figure>
<p><code>bigLm</code> seems to be quite a bit faster than <code>biglm</code>, but how fast is <code>bigLm</code> compared with <code>fastLm</code> (which requires the data to be loaded into memory)? It turns out it’s pretty close on my computer and I don’t even have anything fancy like a solid state drive.</p>
<figure>
<pre><code data-lang="r"><span>suppressMessages</span><span>(</span><span>library</span><span>(</span><span>RcppEigen</span><span>))</span><span>
</span><span>mat.obj</span><span> </span><span>&lt;-</span><span> </span><span>big_mat</span><span>[,]</span><span>
</span><span>## both using the LLT decomposition
</span><span>res</span><span> </span><span>&lt;-</span><span> </span><span>microbenchmark</span><span>(</span><span>fastLm.obj.llt</span><span> </span><span>&lt;-</span><span> </span><span>fastLm</span><span>(</span><span>mat.obj</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>2L</span><span>),</span><span> </span><span># LLT Cholesky
</span><span> </span><span>bigLm.obj.llt</span><span> </span><span>&lt;-</span><span> </span><span>bigLm</span><span>(</span><span>big_mat</span><span>,</span><span> </span><span>y</span><span>),</span><span> </span><span># LLT Cholesky
</span><span> </span><span>fastLm.obj2</span><span> </span><span>&lt;-</span><span> </span><span>fastLmPure</span><span>(</span><span>mat.obj</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>2L</span><span>),</span><span>
</span><span>bigLm.obj2</span><span> </span><span>&lt;-</span><span> </span><span>bigLmPure</span><span>(</span><span>big_mat</span><span>,</span><span> </span><span>y</span><span>),</span><span> </span><span>## a slightly faster version that doesn't check for intercept
</span><span> </span><span>fastLm.obj.ldlt</span><span> </span><span>&lt;-</span><span> </span><span>fastLmPure</span><span>(</span><span>mat.obj</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>3L</span><span>),</span><span> </span><span># LDLT Cholesky
</span><span> </span><span>bigLm.obj.ldlt</span><span> </span><span>&lt;-</span><span> </span><span>bigLmPure</span><span>(</span><span>big_mat</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>1L</span><span>),</span><span> </span><span># LDLT Cholesky </span><span> </span><span>fastLm.obj.qrpiv</span><span> </span><span>&lt;-</span><span> </span><span>fastLmPure</span><span>(</span><span>mat.obj</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>0L</span><span>),</span><span> </span><span># column-pivoted QR
</span><span> </span><span>fastLm.obj.qr</span><span> </span><span>&lt;-</span><span> </span><span>fastLmPure</span><span>(</span><span>mat.obj</span><span>,</span><span> </span><span>y</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>1L</span><span>),</span><span> </span><span># unpivoted QR
</span><span> </span><span>times</span><span> </span><span>=</span><span> </span><span>25L</span><span>)</span><span>
</span><span>print</span><span>(</span><span>summary</span><span>(</span><span>res</span><span>)[,</span><span>1</span><span>:</span><span>7</span><span>],</span><span> </span><span>digits</span><span> </span><span>=</span><span> </span><span>4</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##                                                      expr    min     lq
## 1       fastLm.obj.llt &lt;- fastLm(mat.obj, y, method = 2L)  4.517  4.732
## 2                      bigLm.obj.llt &lt;- bigLm(big_mat, y)  1.726  1.784
## 3      fastLm.obj2 &lt;- fastLmPure(mat.obj, y, method = 2L)  1.629  1.668
## 4                     bigLm.obj2 &lt;- bigLmPure(big_mat, y)  1.611  1.667
## 5  fastLm.obj.ldlt &lt;- fastLmPure(mat.obj, y, method = 3L)  1.598  1.658
## 6    bigLm.obj.ldlt &lt;- bigLmPure(big_mat, y, method = 1L)  1.617  1.690
## 7 fastLm.obj.qrpiv &lt;- fastLmPure(mat.obj, y, method = 0L) 12.072 13.119
## 8    fastLm.obj.qr &lt;- fastLmPure(mat.obj, y, method = 1L)  9.386  9.772
##     mean median     uq    max
## 1  5.390  5.658  5.849  6.728
## 2  1.932  1.820  1.878  3.325
## 3  1.719  1.678  1.709  2.351
## 4  1.754  1.677  1.742  2.266
## 5  1.741  1.677  1.749  2.373
## 6  1.780  1.726  1.829  2.145
## 7 13.240 13.195 13.356 14.714
## 8 10.228 10.135 10.486 12.356</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>max</span><span>(</span><span>abs</span><span>(</span><span>coef</span><span>(</span><span>fastLm.obj.llt</span><span>)</span><span> </span><span>-</span><span> </span><span>coef</span><span>(</span><span>bigLm.obj.llt</span><span>)))</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] 0</code></pre>
</figure>
<p>Future work would be to try to figure out how to make the QR decomposition memory-feasible and also to write a function for generalized linear models.</p>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/"></div></div><div><a data-url="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/" data-counturl="http://www.r-bloggers.com/fast-and-big-linear-model-fitting-with-bigmemory-and-rcppeigen-2/" data-count="vertical" data-text="Fast and Big Linear Model Fitting with bigmemory and RcppEigen" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://casualinference.org/2016/07/07/big_fast_lm/"> jared huling</a></strong>.</div>
<hr>
<a rel="nofollow" href="http://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="http://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="http://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="http://www.r-bloggers.com/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="http://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="http://www.r-bloggers.com/?s=Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="http://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="http://www.r-bloggers.com/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="http://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="http://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="http://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="http://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="http://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="http://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="http://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="http://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="http://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="http://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="http://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="http://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="http://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="http://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="http://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/LUE1f9Nunso"></a></div>