<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/parallel-vectorized-operations/"></div></div><div><a data-url="https://www.r-bloggers.com/parallel-vectorized-operations/" data-counturl="https://www.r-bloggers.com/parallel-vectorized-operations/" data-count="horizontal" data-text="Parallel Vectorized Operations" 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://datascienceplus.com/parallel-vectorized-operations/"> DataScience+</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>After using R for a few years people come to realize how inefficient loops are (in all languages), even after pre-allocating memory. Then you begin to use the apply functions and revel at their speed. However, once you have datasets > 10-15 million the apply family can begin to creep along (relative to the amount of logic in your function). Luckily, most datasets I work with are between 1 – 5 million records and do not encounter performance issues too often. However, when we do run into large datasets we have our parallel packages.</p>
<h2>Demo Machine</h2>
<p>While writing this demo from my home laptop I was not seeing performance gains in parallel, because I was running out of RAM to maximize the efficiency of parallel processing. Therefore, I decided to checkout Google’s Cloud and was quite happy with the aesthetics and performance of their platform. Now, I do not work for Google, but it is worth checking out their <a target="_blank" rel="nofollow" href="https://cloud.google.com/free-trial/">trial</a>.</p>
<p>custom (8 vCPUs, 32 GB memory)</p>
<h2>For Loop</h2>
<p>Most programmers know to try and avoid loops whenever possible because of they are extremely resource intensive. However, with languages such as R, the majority of the time spent is manipulating the dataset. Oftentimes this includes cleaning and feature engineering which requires user-defined functions. If you have less than 10,000 observations and the function is not overly complex then for loops are fine. The example below processes 150 observations in three hundredth of a second.</p>
<pre>
IrisClassifier  &lt;- function(df,i){
  if(df[1][i,] >= 5.8 &amp; df[4][i,] >= 1.8){
    return('virginica')
  }else if(df[1][i,] &lt;= 5.7 &amp; df[4][i,] &lt;= 1){
    return('setosa')
  }else{
    return('versicolor')
  }
}
iris$Check &lt;- ''
system.time(
  for(i in 1:nrow(iris)){
    iris$Check[i] &lt;- IrisClassifier(iris,i)
  }
)
</pre>
<table>
<tr>
<th>User Time</th>
<th>System Time</th>
<th>Elapsed Time</th>
</tr>
<tr>
<td>0.03</td>
<td>0.00</td>
<td>0.03</td>
</tr>
</table>
<h3>Vectorized Operations</h3>
<p>How does the apply family speed up our functions? It converts a scalar (single item) process to a vector (array) process. Think of a mill having to cut lumber piece-by-piece or having one large saw and applying it to all of the lumber at once. </p>
<pre>
IrisClassifier  &lt;- function(col1,col2){
  if(col1 >= 5.8 &amp; col2 >= 1.8){
    return('virginica')
  }else if(col1 &lt;= 5.7 &amp; col2 &lt;= 1){
    return('setosa')
  }else{
    return('versicolor')
  }
}

system.time(iris$Check &lt;- mapply(psuedoClassifier,iris[,1],iris[,4]))
</pre>
<table>
<tr>
<th>User Time</th>
<th>System Time</th>
<th>Elapsed Time</th>
</tr>
<tr>
<td>0.00</td>
<td>0.00</td>
<td>0.00</td>
</tr>
</table>
<h2>Loop vs. mapply</h2>
<p>Required Libraries:</p>
<pre>
library(doSNOW)
library(foreach)
library(data.table)
library(sqldf)
library(ggplot2)
</pre>
<h3>The Dataset</h3>
<p>For this example we will be using a simple dataset starting with 1,000,000 million observations and increment by 1,000,000 to 30,000,000 million observations. The entire script is located at the end of this example. </p>
<pre>
df &lt;-   df &lt;- data.frame(a = round(rnorm(values[i],mean = 18,sd = 10),0),
                   b = round(rnorm(values[i],mean = 10,sd = 11),0),
                   c = round(rnorm(values[i],mean = 400,sd = 44),0),
                   d = round(rnorm(values[i],mean = 100,sd = 33),0),
                   e = round(rnorm(values[i],mean = 11,sd = 3),0),
                   f = round(rnorm(values[i],mean = 223,sd = 1000),0)
  )
</pre>
<h3>Test Function</h3>
<p>For this example we will use the <code>mapply</code> to show how to apply a function with multiple parameters. I find most articles online only demonstrating how to apply with one parameter so I used this as an excuse to demonstrate applying a function with multiple parameters. </p>
<pre>
unspirited.func &lt;- function(a,b,c,d,e,f){
  if(a > 20 &amp; b  300 &amp; c  30 &amp; log(c)> 6) {
    return('Fail - A')
  }else if(b > 38 &amp; log(c)> 6) {
    return('Fail- B')
  }else if(d > 175 &amp; log(c)> 6) {
    return('Fail - D')
  }else if(e > 18 &amp; log(c)> 6) {
    return('Fail - E')
  }else if(f > 1989 &amp; log(c)> 6) {
    return('Fail - F')
  }else{
    return('Unsure')
  }  
}
</pre>
<h3>Comparing For Loop to Vectorized Operations</h3>
<p><a title="" data-rel="lightbox-0" target="_blank" rel="nofollow" href="https://i2.wp.com/datascienceplus.com/wp-content/uploads/2016/08/loop_mapply.png"><img sizes="(max-width: 490px) 100vw, 490px" alt="loop_mapply" class="wp-image-4454" src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2016/08/loop_mapply-490x490.png?resize=456%2C456" data-recalc-dims="1"></a></p>
<table>
<tr>
<th>Type</th>
<th>Number of Observations</th>
<th>Elapsed Time</th>
</tr>
<tr>
<td>Loop</td>
<td>50000</td>
<td>24.593</td>
</tr>
<tr>
<td>mapply</td>
<td>50000</td>
<td>0.536</td>
</tr>
<tr>
<td>Loop</td>
<td>100000</td>
<td>59.314</td>
</tr>
<tr>
<td>mapply</td>
<td>100000</td>
<td>1.228</td>
</tr>
<tr>
<td>Loop</td>
<td>150000</td>
<td>117.658</td>
</tr>
<tr>
<td>mapply</td>
<td>150000</td>
<td>1.865</td>
</tr>
<tr>
<td>Loop</td>
<td>200000</td>
<td>209.694</td>
</tr>
<tr>
<td>mapply</td>
<td>200000</td>
<td>2.658</td>
</tr>
<tr>
<td>Loop</td>
<td>250000</td>
<td>317.212</td>
</tr>
<tr>
<td>mapply</td>
<td>250000</td>
<td>3.283</td>
</tr>
<tr>
<td>Loop</td>
<td>300000</td>
<td>521.578</td>
</tr>
<tr>
<td>mapply</td>
<td>300000</td>
<td>3.816</td>
</tr>
<tr>
<td>Loop</td>
<td>350000</td>
<td>615.212</td>
</tr>
<tr>
<td>mapply</td>
<td>350000</td>
<td>4.625</td>
</tr>
<tr>
<td>Loop</td>
<td>400000</td>
<td>854.06</td>
</tr>
<tr>
<td>mapply</td>
<td>400000</td>
<td>5.571</td>
</tr>
<tr>
<td>Loop</td>
<td>450000</td>
<td>928.809</td>
</tr>
<tr>
<td>mapply</td>
<td>450000</td>
<td>6.437</td>
</tr>
<tr>
<td>Loop</td>
<td>500000</td>
<td>1210.446</td>
</tr>
<tr>
<td>mapply</td>
<td>500000</td>
<td>7.179</td>
</tr>
</table>
<h2>Mapply vs. Parallel Mapply</h2>
<p><strong>Parallel Operations</strong><br>
Luckily most current laptops, pcs, and cloud machines all offer multiple cores of processing power. Therefore, how does parallel processing work? Essentially, R starts up <strong>n</strong> number of instances and sends subsets of the original data to be processed in those instances using its own processing core, and then finally returning the results back together.</p>
<p><a title="" data-rel="lightbox-1" target="_blank" rel="nofollow" href="https://i0.wp.com/datascienceplus.com/wp-content/uploads/2016/08/mapply_para1.png"><img sizes="(max-width: 490px) 100vw, 490px" alt="mapply_para1" class="wp-image-4463" src="https://i1.wp.com/datascienceplus.com/wp-content/uploads/2016/08/mapply_para1-490x490.png?resize=456%2C456" data-recalc-dims="1"></a></p>
<table>
<tr>
<th>Type</th>
<th>Number of Observations</th>
<th>Elapsed Time</th>
</tr>
<tr>
<td>mapply</td>
<td>1000000</td>
<td>14.851</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>1000000</td>
<td>13.641</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>1000000</td>
<td>9.407</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>1000000</td>
<td>8.741</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>1000000</td>
<td>8.326</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>1000000</td>
<td>8.977</td>
</tr>
<tr>
<td>mapply</td>
<td>5000000</td>
<td>95.012</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>5000000</td>
<td>64.179</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>5000000</td>
<td>49.724</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>5000000</td>
<td>42.357</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>5000000</td>
<td>40.959</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>5000000</td>
<td>40.204</td>
</tr>
<tr>
<td>mapply</td>
<td>10000000</td>
<td>198.36</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>10000000</td>
<td>137.413</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>10000000</td>
<td>108.221</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>10000000</td>
<td>91.929</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>10000000</td>
<td>87.314</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>10000000</td>
<td>87.57</td>
</tr>
<tr>
<td>mapply</td>
<td>15000000</td>
<td>304.673</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>15000000</td>
<td>209.789</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>15000000</td>
<td>162.592</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>15000000</td>
<td>138.99</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>15000000</td>
<td>135.785</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>15000000</td>
<td>132.459</td>
</tr>
<tr>
<td>mapply</td>
<td>20000000</td>
<td>411.984</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>20000000</td>
<td>292.82</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>20000000</td>
<td>224.262</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>20000000</td>
<td>186.6</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>20000000</td>
<td>184.216</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>20000000</td>
<td>179.269</td>
</tr>
<tr>
<td>mapply</td>
<td>25000000</td>
<td>529.586</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>25000000</td>
<td>373.688</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>25000000</td>
<td>282.885</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>25000000</td>
<td>238.923</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>25000000</td>
<td>229.101</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>25000000</td>
<td>227.555</td>
</tr>
<tr>
<td>Parallel-2</td>
<td>30000000</td>
<td>451.788</td>
</tr>
<tr>
<td>Parallel-3</td>
<td>30000000</td>
<td>349.257</td>
</tr>
<tr>
<td>Parallel-4</td>
<td>30000000</td>
<td>286.526</td>
</tr>
<tr>
<td>Parallel-5</td>
<td>30000000</td>
<td>277.594</td>
</tr>
<tr>
<td>Parallel-6</td>
<td>30000000</td>
<td>274.735</td>
</tr>
</table>
<p><strong>Considerations</strong></p>
<ul>
<li>Required Setup time</li>
<li>Parallel will end up using more RAM</li>
<li>Shared server resources</li>
</ul>
<h2>Final Note</h2>
<p>After hearing Max Kuhn speak a few years ago he said always check to see if someone has already written the function you are coding. After, writing this post I did stumble upon some builtin in parallel apply functions. However, I have not researched exactly how these operate. </p>
<p><strong>The Entire Script</strong></p>
<pre>
###############################################################################################################################
# Name             :  Parallel Process Example 
# Date             :  2016-09-03 
# Author           :  Christopher M
# Dept             :  Business Analytics 
# Purpose          :  ~
###############################################################################################################################
# ver    user        date(YYYYMMDD)        change  
# 1.0     ~          20160903              initial
############################################################################################################################### 

library(parallel)
library(ggplot2)

## Display number of CPU cores on host
detectCores(all.tests = FALSE, logical = TRUE)

## Example function for processing
unspirited.func &lt;- function(a,b,c,d,e,f){
  
  if(a > 20 &amp; b  300 &amp; c  30 &amp; log(c)> 6) {
    return('Fail - A')
  }else if(b > 38 &amp; log(c)> 6) {
    return('Fail- B')
  }else if(d > 175 &amp; log(c)> 6) {
    return('Fail - D')
  }else if(e > 18 &amp; log(c)> 6) {
    return('Fail - E')
  }else if(f > 1989 &amp; log(c)> 6) {
    return('Fail - F')
  }else{
    return('Unsure')
  } 
  
}

## kfold function to split data for parallel processing
kfold &lt;- function(df,k){
  require(sqldf)
  if( length(which(colnames(df)=='folds'))>0){
    stop(print('Rename column(s) named folds'))
    break
    
  }
  #randomize the data
  df&lt;-sqldf(&quot;SELECT * FROM df order by random()&quot;)
  
  #Create equally size folds
  df$folds &lt;- cut(seq(1,nrow(df)),breaks=k,labels=FALSE)
  
  return(df)
  
}

## function for parallel processing
parallelApply &lt;- function(df,cols,func,cores){
  
  require(doSNOW)
  require(foreach)
  require(data.table)
  cl &lt;- makeCluster(cores, type=&quot;SOCK&quot;)
  registerDoSNOW(cl)
  
  ## Create ID to compute in parallel
  df &lt;- kfold(df,cores)
  
  ## Process data in parallel
  system.time(NewDataFrame &lt;- foreach(i = 1:cores) %dopar% {
    tmpdata &lt;- subset(df, folds == i)
    mapply(func,tmpdata[,cols[1]],tmpdata[,cols[2]],tmpdata[,cols[3]],tmpdata[,cols[4]],tmpdata[,cols[5]],tmpdata[,cols[6]])
    
  })
  
  ## Bind data back into dataframe
  NewDataFrame &lt;- rbindlist(Map(as.data.frame, NewDataFrame))
  colnames(NewDataFrame) &lt;- c('ParRow')
  df &lt;- cbind(df,NewDataFrame)
  stopCluster(cl)
  return(df)
  
}

## values for dataframe length
values &lt;- seq(1e6,30e6,1e6)

capture &lt;- data.frame()

for(i in 1:length(values)){
  print(paste(&quot;processing:&quot;,values[i],&quot;rows. There are&quot;,length(values)-i,&quot;iterations left to complete&quot;))
  
  df &lt;- data.frame(a = round(rnorm(values[i],mean = 18,sd = 10),0),
                   b = round(rnorm(values[i],mean = 10,sd = 11),0),
                   c = round(rnorm(values[i],mean = 400,sd = 44),0),
                   d = round(rnorm(values[i],mean = 100,sd = 33),0),
                   e = round(rnorm(values[i],mean = 11,sd = 3),0),
                   f = round(rnorm(values[i],mean = 223,sd = 1000),0)
  )
  ##______________________________________________________________________________
  ## Apply
  
  performance &lt;- system.time(df$Check &lt;- mapply(unspirited.func,df[,1],df[,2],df[,3],df[,4],df[,5],df[,6]))
  capture &lt;- rbind(capture,data.frame(Type = 'mapply',Rows = values[i],elapsed = performance[3],PercentDifference = 1))
  df$Check &lt;- NULL
  print('finished')
  print(capture)
  ##______________________________________________________________________________
  ## Parallel Apply
  base &lt;- as.numeric(subset(capture,Rows == values[i] &amp; Type == 'mapply')[3])  
  for(x in 2:6){
    print(paste('running on',x,'cores'))
    performance &lt;- system.time(df &lt;- parallelApply(df,c(1,2,3,4,5,6),unspirited.func,x))
    capture &lt;- rbind(capture,data.frame(Type = paste('Parallel-',x,sep=''),Rows = values[i],elapsed = performance[3],
                                        PercentDifference = abs(1-(performance[3]/base))))
    df$ParRow &lt;- NULL
    df$folds &lt;- NULL
  }
  gc()
  print(capture)
}
options(scipen=999)

## Example plots
ggplot(subset(capture,Type != 'Loop'),aes(Rows,elapsed,color = Type))+
  geom_line( aes(linetype=Type))+
  geom_point(size=3 )+
  ylab(&quot;elapsed (seconds)&quot;) +
  geom_text(data=subset(capture,Rows ==max(capture$Rows)),
            aes(label=Type))+
  ggtitle(&quot;Mapply  ~ Parallel&quot;)


tmp &lt;- subset(capture,Type != 'mapply')
tmp$PercentDifference &lt;- tmp$PercentDifference + 1
mapply &lt;- subset(capture,Type == 'mapply')
capture_ &lt;- rbind(tmp,mapply)

ggplot(subset(capture_,Type != 'Loop'),aes(Rows,PercentDifference,color = Type))+
  geom_line( aes(linetype=Type))+
  geom_point(size=3 )+
  ylab(&quot;Performance Increase&quot;) +
  ggtitle(&quot;Mapply  ~ Parallel&quot;) +
  scale_x_continuous(breaks = seq(5e6,30e6,5e6))+
  scale_y_continuous(breaks = seq(0,3,.1))
</pre>
<ul></ul>
<p><strong>
<p>Related Post</p>
<p>
<ol>
<li><a title="Permanent Link toR Markdown: How to number and reference tables" target="_blank" rel="nofollow" href="http://datascienceplus.com/r-markdown-how-to-number-and-reference-tables/">R Markdown: How to number and reference tables</a></li>
<li><a title="Permanent Link toRDBL – manipulate data in-database with R code only" target="_blank" rel="nofollow" href="http://datascienceplus.com/rdbl-manipulate-data-in-database-with-r-code-only/">RDBL – manipulate data in-database with R code only</a></li>
<li><a title="Permanent Link toR Markdown: How to format tables and figures in .docx files" target="_blank" rel="nofollow" href="http://datascienceplus.com/r-markdown-how-to-format-tables-and-figures-in-docx-files/">R Markdown: How to format tables and figures in .docx files</a></li>
<li><a title="Permanent Link toR Markdown: How to insert page breaks in a MS Word document" target="_blank" rel="nofollow" href="http://datascienceplus.com/r-markdown-how-to-insert-page-breaks-in-a-ms-word-document/">R Markdown: How to insert page breaks in a MS Word document</a></li>
<li><a title="Permanent Link toWorking on Data-Warehouse (SQL) with R" target="_blank" rel="nofollow" href="http://datascienceplus.com/working-on-data-warehouse-sql-with-r/">Working on Data-Warehouse (SQL) with R</a></li>
</ol></strong>
<div>
<a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=KKmRJFYrfuk:hVyA9rfhL6A:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/datascienceplus?i=KKmRJFYrfuk:hVyA9rfhL6A:D7DqB2pKExk" border="0"></a> <a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=KKmRJFYrfuk:hVyA9rfhL6A:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/datascienceplus?d=qj6IDK7rITs" border="0"></a> <a target="_blank" rel="nofollow" href="http://feeds.feedburner.com/~ff/datascienceplus?a=KKmRJFYrfuk:hVyA9rfhL6A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/datascienceplus?d=yIl2AUoC8zA" border="0"></a>
</div>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="https://www.r-bloggers.com/parallel-vectorized-operations/"></div></div><div><a data-url="https://www.r-bloggers.com/parallel-vectorized-operations/" data-counturl="https://www.r-bloggers.com/parallel-vectorized-operations/" data-count="vertical" data-text="Parallel Vectorized Operations" 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://datascienceplus.com/parallel-vectorized-operations/"> DataScience+</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 title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/?s=Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/ApeCWnjqyIc"></a></div>