<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/the-progress-bar-just-got-a-lot-cheaper/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://peter.solymos.org/code/2018/01/23/the-progress-bar-just-got-a-lot-cheaper.html"> Peter Solymos - R related posts</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>The <a rel="nofollow" href="http://cran.r-project.org/package=pbapply" target="_blank"><strong>pbapply</strong></a> R package that adds progress bar to vectorized functions has been know to accumulate overhead when calling <code>parallel::mclapply</code> with forking (see <a rel="nofollow" href="http://peter.solymos.org/code/2016/09/11/what-is-the-cost-of-a-progress-bar-in-r.html" target="_blank">this post</a> for more background on the issue). Strangely enough, a <a rel="nofollow" href="https://github.com/psolymos/pbapply/issues/30" target="_blank">GitHub issue</a> held the key to the solution that I am going to outline below. Long story short: forking is no longer expensive with <strong>pbapply</strong>, and as it turns out, it never was.</p>
<p>The issue mentioned <code>parallel::makeForkCluster</code> as the way to set up a Fork cluster, which, according to the help page, ‘<em>is merely a stub on Windows. On Unix-alike platforms it creates the worker process by forking</em>’.<br>
So I looked at some timings starting with one of the examples on the <code>?pbapply</code> help page:</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>pbapply</span><span>)</span><span>
</span><span>set.seed</span><span>(</span><span>1234</span><span>)</span><span>
</span><span>n</span><span> </span><span>&lt;-</span><span> </span><span>200</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>rnorm</span><span>(</span><span>n</span><span>)</span><span>
</span><span>y</span><span> </span><span>&lt;-</span><span> </span><span>rnorm</span><span>(</span><span>n</span><span>,</span><span> </span><span>crossprod</span><span>(</span><span>t</span><span>(</span><span>model.matrix</span><span>(</span><span>~</span><span> </span><span>x</span><span>)),</span><span> </span><span>c</span><span>(</span><span>0</span><span>,</span><span> </span><span>1</span><span>)),</span><span> </span><span>sd</span><span> </span><span>=</span><span> </span><span>0.5</span><span>)</span><span>
</span><span>d</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>y</span><span>,</span><span> </span><span>x</span><span>)</span><span>
</span><span>mod</span><span> </span><span>&lt;-</span><span> </span><span>lm</span><span>(</span><span>y</span><span> </span><span>~</span><span> </span><span>x</span><span>,</span><span> </span><span>d</span><span>)</span><span>
</span><span>ndat</span><span> </span><span>&lt;-</span><span> </span><span>model.frame</span><span>(</span><span>mod</span><span>)</span><span>
</span><span>B</span><span> </span><span>&lt;-</span><span> </span><span>100</span><span>
</span><span>bid</span><span> </span><span>&lt;-</span><span> </span><span>sapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>function</span><span>(</span><span>i</span><span>)</span><span> </span><span>sample</span><span>(</span><span>nrow</span><span>(</span><span>ndat</span><span>),</span><span> </span><span>nrow</span><span>(</span><span>ndat</span><span>),</span><span> </span><span>TRUE</span><span>))</span><span>
</span><span>fun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>z</span><span>)</span><span> </span><span>{</span><span>
</span><span>if</span><span> </span><span>(</span><span>missing</span><span>(</span><span>z</span><span>))</span><span>
</span><span>z</span><span> </span><span>&lt;-</span><span> </span><span>sample</span><span>(</span><span>nrow</span><span>(</span><span>ndat</span><span>),</span><span> </span><span>nrow</span><span>(</span><span>ndat</span><span>),</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>coef</span><span>(</span><span>lm</span><span>(</span><span>mod</span><span>$</span><span>call</span><span>$</span><span>formula</span><span>,</span><span> </span><span>data</span><span>=</span><span>ndat</span><span>[</span><span>z</span><span>,]))</span><span>
</span><span>}</span><span> </span><span>## forking with mclapply</span><span>
</span><span>system.time</span><span>(</span><span>res1</span><span> </span><span>&lt;-</span><span> </span><span>pblapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>function</span><span>(</span><span>i</span><span>)</span><span> </span><span>fun</span><span>(</span><span>bid</span><span>[,</span><span>i</span><span>]),</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>2L</span><span>))</span><span>
</span><span>## |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 01s</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.587 0.919 0.845 </span><span>
</span><span>## forking with parLapply</span><span>
</span><span>cl</span><span> </span><span>&lt;-</span><span> </span><span>makeForkCluster</span><span>(</span><span>2L</span><span>)</span><span>
</span><span>system.time</span><span>(</span><span>res2</span><span> </span><span>&lt;-</span><span> </span><span>pblapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>function</span><span>(</span><span>i</span><span>)</span><span> </span><span>fun</span><span>(</span><span>bid</span><span>[,</span><span>i</span><span>]),</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>))</span><span>
</span><span>## |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 00s</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.058 0.009 0.215 </span><span>
</span><span>stopCluster</span><span>(</span><span>cl</span><span>)</span><span>
</span><span>## Socket cluster (need to pass objects to workers)</span><span>
</span><span>cl</span><span> </span><span>&lt;-</span><span> </span><span>makeCluster</span><span>(</span><span>2L</span><span>)</span><span>
</span><span>clusterExport</span><span>(</span><span>cl</span><span>,</span><span> </span><span>c</span><span>(</span><span>&quot;fun&quot;</span><span>,</span><span> </span><span>&quot;mod&quot;</span><span>,</span><span> </span><span>&quot;ndat&quot;</span><span>,</span><span> </span><span>&quot;bid&quot;</span><span>))</span><span>
</span><span>system.time</span><span>(</span><span>res3</span><span> </span><span>&lt;-</span><span> </span><span>pblapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>function</span><span>(</span><span>i</span><span>)</span><span> </span><span>fun</span><span>(</span><span>bid</span><span>[,</span><span>i</span><span>]),</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>))</span><span>
</span><span>## |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 00s</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.053 0.008 0.169 </span><span>
</span><span>stopCluster</span><span>(</span><span>cl</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>Forking with <code>mclapply</code> is still pricey, but the almost equivalent <code>makeForkCluster</code> trick, that does not require objects to be passed to workers due to the shared memory nature of the process, is pretty close to the ordinary Socket cluster option.</p>
<p>What if I used this trick in the package? I would then create a Fork cluster<br>
(<code>cl &lt;- makeForkCluster(cl)</code>), run <code>parLapply(cl, ...)</code>, and destroy the cluster with <code>on.exit(stopCluster(cl), add = TRUE)</code>. So I created a <a rel="nofollow" href="https://github.com/psolymos/pbapply/tree/fork-cluster-speedup" target="_blank">branch</a> to do some tests:</p>
<div>
<div>
<pre><code><span>ncl</span><span> </span><span>&lt;-</span><span> </span><span>2</span><span>
</span><span>B</span><span> </span><span>&lt;-</span><span> </span><span>1000</span><span>
</span><span>fun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>x</span><span>)</span><span> </span><span>{</span><span>
</span><span>Sys.sleep</span><span>(</span><span>0.01</span><span>)</span><span>
</span><span>x</span><span>^</span><span>2</span><span>
</span><span>}</span><span>
</span><span>library</span><span>(</span><span>pbmcapply</span><span>)</span><span>
</span><span>(</span><span>t</span><span>1</span><span> </span><span>&lt;-</span><span> </span><span>system.time</span><span>(</span><span>pbmclapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>mc.cores</span><span> </span><span>=</span><span> </span><span>ncl</span><span>)))</span><span>
</span><span>## |========================================================| 100%, ETA 00:00</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.242 0.114 5.461 </span><span>
</span><span>library</span><span>(</span><span>pbapply</span><span>)</span><span> </span><span># 1.3-4 CRAN version</span><span>
</span><span>(</span><span>t</span><span>2</span><span> </span><span>&lt;-</span><span> </span><span>system.time</span><span>(</span><span>pblapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>)))</span><span>
</span><span>## |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 07s</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.667 1.390 6.547 </span><span>
</span><span>library</span><span>(</span><span>pbapply</span><span>)</span><span> </span><span># 1.3-5 fork-cluster-speedup branch</span><span>
</span><span>(</span><span>t</span><span>3</span><span> </span><span>&lt;-</span><span> </span><span>system.time</span><span>(</span><span>pblapply</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>)))</span><span>
</span><span>## |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 06s</span><span>
</span><span>## user system elapsed </span><span>
</span><span>## 0.225 0.100 5.710 </span><span>
</span></code></pre>
</div>
</div>
<p>Really nice so far: <strong>pbapply</strong> caught up to forking based timings with <strong>pbmcapply</strong>. Let’s see a bit more extensive runs to see how the number of progress bar updates affects the timings. If things work as I hope,<br>
there shouldn’t be an increase with the new forking idea:</p>
<div>
<div>
<pre><code><span>timer_fun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>X</span><span>,</span><span> </span><span>FUN</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>...</span><span>)</span><span> </span><span>{</span><span>
</span><span>pbo</span><span> </span><span>&lt;-</span><span> </span><span>pboptions</span><span>(</span><span>nout</span><span> </span><span>=</span><span> </span><span>nout</span><span>)</span><span>
</span><span>on.exit</span><span>(</span><span>pboptions</span><span>(</span><span>pbo</span><span>))</span><span>
</span><span>unname</span><span>(</span><span>system.time</span><span>(</span><span>pblapply</span><span>(</span><span>X</span><span>,</span><span> </span><span>FUN</span><span>,</span><span> </span><span>...</span><span>))[</span><span>3</span><span>])</span><span>
</span><span>}</span><span>
</span><span>timer_NULL</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>
</span><span>nout1</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>NULL</span><span>),</span><span>
</span><span>nout10</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>NULL</span><span>),</span><span>
</span><span>nout100</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>NULL</span><span>),</span><span>
</span><span>nout1000</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>NULL</span><span>))</span><span>
</span><span>unlist</span><span>(</span><span>timer_NULL</span><span>)</span><span>
</span><span>## nout1 nout10 nout100 nout1000 </span><span>
</span><span>## 12.221 11.899 11.775 11.260 </span><span>
</span><span>cl</span><span> </span><span>&lt;-</span><span> </span><span>makeCluster</span><span>(</span><span>ncl</span><span>)</span><span>
</span><span>timer_cl</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>
</span><span>nout1</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>),</span><span>
</span><span>nout10</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>),</span><span>
</span><span>nout100</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>),</span><span>
</span><span>nout1000</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>))</span><span>
</span><span>stopCluster</span><span>(</span><span>cl</span><span>)</span><span>
</span><span>unlist</span><span>(</span><span>timer_cl</span><span>)</span><span>
</span><span>## nout1 nout10 nout100 nout1000 </span><span>
</span><span>## 6.033 6.091 6.011 6.273 </span><span>
</span><span>## forking with 1.3-4 CRAN version</span><span>
</span><span>timer_mc</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>
</span><span>nout1</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout10</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout100</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout1000</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>))</span><span>
</span><span>unlist</span><span>(</span><span>timer_mc</span><span>)</span><span>
</span><span>## nout1 nout10 nout100 nout1000 </span><span>
</span><span>## 5.563 5.659 6.620 10.692 </span><span>
</span><span>## forking with 1.3-5 fork-cluster-speedup branch</span><span>
</span><span>timer_new</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>
</span><span>nout1</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout10</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>10</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout100</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>),</span><span>
</span><span>nout1000</span><span> </span><span>=</span><span> </span><span>timer_fun</span><span>(</span><span>1</span><span>:</span><span>B</span><span>,</span><span> </span><span>fun</span><span>,</span><span> </span><span>nout</span><span> </span><span>=</span><span> </span><span>1000</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>ncl</span><span>))</span><span>
</span><span>unlist</span><span>(</span><span>timer_new</span><span>)</span><span>
</span><span>## nout1 nout10 nout100 nout1000 </span><span>
</span><span>## 5.480 5.574 5.665 6.063 </span><span>
</span></code></pre>
</div>
</div>
<p>The new implementation with the Fork cluster trick hands down beat the old implementation using <code>mclapply</code>. I wonder what is causing the<br>
wildly different timings results. Is it due to all the other<br>
<code>mclapply</code> arguments that give control over pre-scheduling, cleanup, and RNG seeds?</p>
<p>The new branch can be installed as:</p>
<div>
<div>
<pre><code><span>devtools</span><span>::</span><span>install_github</span><span>(</span><span>&quot;psolymos/pbapply&quot;</span><span>,</span><span> </span><span>ref</span><span> </span><span>=</span><span> </span><span>&quot;fork-cluster-speedup&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>I am a bit reluctant of merging the new branch for the following reasons:</p>
<ul>
<li><code>makeForkCluster</code> was already an option before by explicitly stating the cluster to be a Fork;</li>
<li>by hiding the process of creating and destroying the cluster, user options are restricted (i.e. no control over RNGs, which can be a major drawback for simulations);</li>
<li><code>mclapply</code> wasn’t so bad to begin with, because the number of updates were capped by the <code>nout</code> option.</li>
</ul>
<p>I would recommend the following workflow that is based purely on the stable CRAN version:</p>
<div>
<div>
<pre><code><span>cl</span><span> </span><span>&lt;-</span><span> </span><span>makeForkCluster</span><span>(</span><span>2L</span><span>)</span><span>
</span><span>output</span><span> </span><span>&lt;-</span><span> </span><span>pblapply</span><span>(</span><span>...</span><span>,</span><span> </span><span>cl</span><span> </span><span>=</span><span> </span><span>cl</span><span>)</span><span>
</span><span>stopCluster</span><span>(</span><span>cl</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>As always, I am keen on hearing what you think: either in the comments or on <a rel="nofollow" href="https://github.com/psolymos/pbapply/issues/31" target="_blank">GitHub</a>.</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="http://peter.solymos.org/code/2018/01/23/the-progress-bar-just-got-a-lot-cheaper.html"> Peter Solymos - R related posts</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/uAo2717cB_Q" height="1"></a></div>