<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ R Language - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ R Language - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 03 Jun 2026 21:41:47 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/r/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Create Scatterplots and Model Data in R Using ggplot2 ]]>
                </title>
                <description>
                    <![CDATA[ You can use R as a powerful tool for data analysis, data visualization, and statistical modelling. In this guide, you’ll learn how to load real-world data into R, visualize patterns using ggplot2, build simple linear and logistic regression models, a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-scatterplots-and-model-data-in-r/</link>
                <guid isPermaLink="false">695ba922d307c8d32fc522ea</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tiffany Mojo Omondi ]]>
                </dc:creator>
                <pubDate>Mon, 05 Jan 2026 12:05:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767614352690/8b993426-f193-4ff3-b5ec-dd6dda11028e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can use R as a powerful tool for data analysis, data visualization, and statistical modelling. In this guide, you’ll learn how to load real-world data into R, visualize patterns using ggplot2, build simple linear and logistic regression models, and interpret the models. By the end, you should know how to use R for your own projects.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-data-types-in-r">How to Use Data Types in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-data-structures-in-r">How to Use Data Structures in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-import-data-in-r">How to Import Data in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-visualize-data-with-ggplot2">How to Visualize Data with ggplot2</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-statistical-models-in-r">How to Build Statistical Models in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we get started, you should have the following:</p>
<ul>
<li><p>R installed (version 4.0 or higher).</p>
</li>
<li><p>RStudio installed (recommended for beginners).</p>
</li>
<li><p>Basic familiarity with programming concepts such as variables and functions.</p>
</li>
<li><p>A basic understanding of statistics (mean, correlation, regression).</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</h2>
<p>Before you start working with data, load the required libraries:</p>
<pre><code class="lang-plaintext">library(tidyverse)   # Data manipulation + ggplot2
library(readxl)      # Importing Excel files
</code></pre>
<p>These load the required libraries into the R. <code>tidyverse</code> is a collection of packages used for data manipulation and visualization, including <code>ggplot2</code>. <code>readxl</code> allows you to import Excel files directly into R without converting them to CSV format first.</p>
<h2 id="heading-how-to-use-data-types-in-r">How to Use Data Types in R</h2>
<p>Knowing data types helps you avoid errors and choose the right analysis methods.</p>
<h3 id="heading-common-data-types">Common Data Types</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Data type</td><td>Example</td><td>Use case</td></tr>
</thead>
<tbody>
<tr>
<td>Numeric</td><td><code>x &lt;- 5.7</code></td><td>Measurements, prices</td></tr>
<tr>
<td>Integer</td><td><code>y &lt;- 10L</code></td><td>Counts</td></tr>
<tr>
<td>Character</td><td><code>"House prices"</code></td><td>Text labels</td></tr>
<tr>
<td>Logical</td><td><code>TRUE</code></td><td>Conditions</td></tr>
<tr>
<td>Complex</td><td><code>2 + 3i</code></td><td>Advanced math</td></tr>
</tbody>
</table>
</div><h3 id="heading-numeric-data-types-in-r">Numeric Data Types in R</h3>
<pre><code class="lang-r">price &lt;- <span class="hljs-number">199.99</span>
tax &lt;- <span class="hljs-number">16.5</span>
total_cost &lt;- price + tax
total_cost
</code></pre>
<p>Numeric data is used for continuous values such as measurements, prices, or averages. As you can see, these are numeric values that can be used in a calculation. Numeric data types allow arithmetic operations such as addition, subtraction, multiplication, and division.</p>
<h3 id="heading-integer-data-types-in-r">Integer Data Types in R</h3>
<pre><code class="lang-r">students &lt;- <span class="hljs-number">30L</span>
classes &lt;- <span class="hljs-number">4L</span>
total_students &lt;- students * classes
total_students
</code></pre>
<p>Integers are whole numbers and are commonly used for counting. The <code>L</code> tells R that the values are integers. Integers are useful when working with counts, indexes, or discrete values.</p>
<h3 id="heading-character-data-types-in-r">Character Data Types in R</h3>
<pre><code class="lang-r">course_name &lt;- <span class="hljs-string">"Data Science"</span>
university &lt;- <span class="hljs-string">"Harvard University"</span>
paste(course_name, <span class="hljs-string">"at"</span>, university)
</code></pre>
<p>Character data is used to store text such as names, labels, or categories. The example above shows how character data can be combined using the <code>paste()</code> function. This data type cannot be used in mathematical operations.</p>
<h3 id="heading-logical-data-types-in-r">Logical Data Types in R</h3>
<pre><code class="lang-r">score &lt;- <span class="hljs-number">75</span>
passed &lt;- score &gt;= <span class="hljs-number">50</span>
passed
</code></pre>
<p>Logical data represents Boolean values: <code>TRUE</code> or <code>FALSE</code>. These are commonly used in conditions and filtering. Here, R evaluates a condition and returns <code>TRUE</code> because the score meets the requirement. Logical values are essential in decision-making and control flow.</p>
<h3 id="heading-complex-data-types-in-r">Complex Data Types in R</h3>
<p>Complex numbers contain both real and imaginary parts and are mostly used in advanced mathematical computations.</p>
<pre><code class="lang-r">z &lt;- <span class="hljs-number">2</span> + <span class="hljs-number">3i</span>
Mod(z)
</code></pre>
<p>This example calculates the magnitude of a complex number. Complex data types are rarely used in basic data analysis but are available in R.</p>
<h2 id="heading-how-to-use-data-structures-in-r">How to Use Data Structures in R</h2>
<p>R stores data in different structures depending on your goals. This is important because choosing the right structure makes operations easier. Its functions behave differently depending on the structure. Moreover, structures help R understand whether your data are numbers, categories, or text.</p>
<h3 id="heading-common-data-structures-in-r">Common Data Structures in R</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Structure</td><td>Best for</td></tr>
</thead>
<tbody>
<tr>
<td>Vector</td><td>Single column of data</td></tr>
<tr>
<td>Matrix</td><td>Numeric tables</td></tr>
<tr>
<td>Data Frame</td><td>Spreadsheet-like data</td></tr>
<tr>
<td>List</td><td>Mixed objects</td></tr>
</tbody>
</table>
</div><pre><code class="lang-r">vec &lt;- c(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)
mat &lt;- matrix(<span class="hljs-number">1</span>:<span class="hljs-number">9</span>, nrow = <span class="hljs-number">3</span>)
df &lt;- data.frame(Name = c(<span class="hljs-string">"Car"</span>, <span class="hljs-string">"Bike"</span>), Number = c(<span class="hljs-number">110</span>, <span class="hljs-number">95</span>))
lst &lt;- list(numbers = vec, matrix = mat, info = df)

str(lst) <span class="hljs-comment">##shows the structure of the list</span>
</code></pre>
<p>Lets understand the code above:</p>
<ul>
<li><p><code>vec</code> is a vector that stores a single type of data.</p>
</li>
<li><p><code>mat</code> is a matrix that organizes numeric values into rows and columns.</p>
</li>
<li><p><code>df</code> is a data frame that works like a spreadsheet, allowing different data types in each column.</p>
</li>
<li><p><code>lst</code> is a list that stores multiple objects of different types.</p>
</li>
<li><p>The <code>str()</code> function shows how these objects are nested within the list.</p>
</li>
</ul>
<h2 id="heading-how-to-import-data-in-r"><strong>How to Import Data in R</strong></h2>
<p>Now you can start working with your real data. You can import files into R by copying the path of the CSV or Excel file and pasting it into the command.</p>
<p><strong>For Windows:</strong> Replace single backward slashes / with either double backward slashes \ or single forward slashes \. For example:</p>
<pre><code class="lang-r">
Windows
```r
data &lt;- read.csv("C:\\Users\\file\\Documents\\data.csv") or 
data &lt;- read.csv("C:/Users/file/Documents/data.csv")
</code></pre>
<p><strong>For macOS/Linux:</strong> Single forward slashes work fine:</p>
<pre><code class="lang-r">macOS/Linux
data &lt;- read.csv(<span class="hljs-string">"/Users/file/Documents/data.csv"</span>)
</code></pre>
<h3 id="heading-how-to-read-a-csv-and-excel-file"><strong>How to Read a CSV and Excel File</strong></h3>
<pre><code class="lang-r"><span class="hljs-comment">#Import CSV file </span>
data &lt;- read.csv(<span class="hljs-string">"C:/Users/file/Documents/data.csv"</span>) or data &lt;- read.csv(<span class="hljs-string">"C:\\Users\\file\\Documents\\data.csv"</span>) <span class="hljs-comment">## for windows</span>

head(data.csv)
</code></pre>
<p>You can import a CSV file into R using a file path. On Windows systems, file paths can use either double forward slashes (<code>//</code>) or double backslashes (<code>\</code>). The imported data is stored as a data frame named data.</p>
<pre><code class="lang-r">data_excel &lt;- read_excel(<span class="hljs-string">"C:/Users/file/Documents/HR Data Set.xlsx"</span>)
head(data_excel)
</code></pre>
<p>You can import an Excel file into R using the code <code>read_excel()</code> function from the <code>readxl</code> package. The <code>head()</code> function is then used to preview the first few rows of the dataset.</p>
<p>Use the following commands to understand your data:</p>
<pre><code class="lang-r">str(data.csv)
summary(data.csv)

str(data_excel)
summary(data_excel)
</code></pre>
<p><code>str()</code> shows the structure of the dataset, including column names and data types. <code>summary()</code> provides descriptive statistics such as minimum, maximum, mean, and quartiles for each variable. Together, these functions help you understand the dataset before analysis.</p>
<h2 id="heading-how-to-visualize-data-with-ggplot2"><strong>How to Visualize Data with ggplot2</strong></h2>
<p>Visualization helps you spot patterns before you build models.</p>
<h3 id="heading-scatter-plot-example"><strong>Scatter Plot Example</strong></h3>
<p>We’ll use the built-in <code>mtcars</code> dataset in R. First, load the library to make it available for use:</p>
<pre><code class="lang-r">data(mtcars)
<span class="hljs-keyword">library</span>(ggplot2)

ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = <span class="hljs-number">3</span>,color=<span class="hljs-string">"blue"</span>) +geom_smooth(method=<span class="hljs-string">"lm"</span>,color=<span class="hljs-string">"red"</span>,se=<span class="hljs-literal">FALSE</span>)+
  labs(
    title = <span class="hljs-string">"Fuel Efficiency by Weight and Cylinders"</span>,
    x = <span class="hljs-string">"Weight (1000 lbs)"</span>,
    y = <span class="hljs-string">"Miles per Gallon"</span>
  ) +
  theme_minimal()
</code></pre>
<p>Let us break down the code to grasp it fully:</p>
<ul>
<li><p><code>data(mtcars)</code> loads the built-in <code>mtcars</code> dataset, which contains information about car specifications.</p>
</li>
<li><p><code>library(ggplot2)</code> enables data visualization.</p>
</li>
<li><p><code>aes()</code> was used to insert your dataset columns, which defines the <code>x</code> and <code>y</code> values.</p>
</li>
<li><p><code>aes()</code> was used to design the plot outside. For example, set point <code>size</code> and <code>color</code>.</p>
</li>
<li><p><code>geom_smooth()</code> wass used to add a trend line with. Here, we use <code>method="lm"</code> to fit a linear regression line. The <code>se=TRUE/FALSE</code> option controls the shading for confidence intervals. Use <code>TRUE</code> if you want the shading and <code>FALSE</code> if you don’t.</p>
</li>
<li><p><code>labs()</code> was used for label the plot and set the <code>title</code>, <code>x</code>-axis, and <code>y</code>-axis labels.</p>
</li>
<li><p>Finally, we set the plot theme using <code>theme_minimal()</code>.</p>
</li>
</ul>
<p>Running this code will produce a scatterplot showing fuel efficiency by weight and cylinders. The plot should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765914755069/8921e803-7fa6-4705-802c-23ff8918bee5.png" alt="Scatterplot of mpg against vehicle weight with regression line" class="image--center mx-auto" width="912" height="527" loading="lazy"></p>
<h2 id="heading-how-to-build-statistical-models-in-r"><strong>How to Build Statistical Models in R</strong></h2>
<h3 id="heading-linear-regression"><strong>Linear Regression</strong></h3>
<p>You can use linear regression for continuous outcomes, basically to predict numerical values. For example, to predict a car’s miles per gallon (<code>mpg</code>) based on weight (<code>wt</code>) and horsepower (<code>hp</code>), you can use this formula:</p>
<pre><code class="lang-r">lm_model &lt;- lm(mpg ~ wt + hp, data = mtcars)
summary(lm_model)
</code></pre>
<p>But what does it mean?</p>
<ul>
<li><p><code>lm()</code> stands for linear model.</p>
</li>
<li><p>The response variable is <code>mpg</code>. This is the outcome you want to predict.</p>
</li>
<li><p>Predictor variables are <code>wt</code> and <code>hp</code>. These explain changes in the response.</p>
</li>
</ul>
<p>Once you run the model, it should look like this in your console:</p>
<pre><code class="lang-r">Call:
lm(formula = mpg ~ wt + hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-<span class="hljs-number">3.941</span> -<span class="hljs-number">1.600</span> -<span class="hljs-number">0.182</span>  <span class="hljs-number">1.050</span>  <span class="hljs-number">5.854</span> 

Coefficients:
            Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept) <span class="hljs-number">37.22727</span>    <span class="hljs-number">1.59879</span>  <span class="hljs-number">23.285</span>  &lt; <span class="hljs-number">2e-16</span> ***
wt          -<span class="hljs-number">3.87783</span>    <span class="hljs-number">0.63273</span>  -<span class="hljs-number">6.129</span> <span class="hljs-number">1.12e-06</span> ***
hp          -<span class="hljs-number">0.03177</span>    <span class="hljs-number">0.00903</span>  -<span class="hljs-number">3.519</span>  <span class="hljs-number">0.00145</span> ** 
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

Residual standard error: <span class="hljs-number">2.593</span> on <span class="hljs-number">29</span> degrees of freedom
Multiple R-squared:  <span class="hljs-number">0.8268</span>,    Adjusted R-squared:  <span class="hljs-number">0.8148</span> 
<span class="hljs-literal">F</span>-statistic: <span class="hljs-number">69.21</span> on <span class="hljs-number">2</span> and <span class="hljs-number">29</span> DF,  p-value: <span class="hljs-number">9.109e-12</span>
</code></pre>
<p>Here’s an interpretation of the linear regression model:</p>
<ul>
<li><p>You created a model on miles per gallon (<code>mpg</code>) based on weight (<code>wt</code>) and horsepower (<code>hp</code>).</p>
</li>
<li><p>The intercept <code>37.227</code> is the <code>mpg</code> when <code>wt=0</code> and <code>hp=0</code>. In other words, when all other variables are <code>0</code>, the base <code>mpg</code> is <code>37.227</code>. The intercept is always the baseline value of the outcome when all other variables in the model are zero.</p>
</li>
<li><p>With every additional unit of weight (1000lbs), the <code>mpg</code> decreases by <code>3.877</code>. This variable affects the <code>mpg</code> greatly as seen with the <code>p-value</code>. The <code>p-value</code> is &lt;0.001, hence strong and statistically significant.</p>
</li>
<li><p>With every additional unit of horsepower, the <code>mpg</code> decreases by <code>0.031</code>. This variable affects the <code>mpg</code>, as seen with the <code>p-value</code> being <code>0.00145</code>, which is <strong>less than 0.01</strong>, indicating that horsepower is a statistically significant predictor of <code>mpg</code>, although its effect is smaller compared to vehicle weight.</p>
</li>
</ul>
<h3 id="heading-does-the-model-fit-the-data-and-why">Does the Model Fit the Data, and Why?</h3>
<p>The R-squared value shows that 83% of the variation in <code>mpg</code> is explained by weight and horsepower.</p>
<p><strong>Summary of the interpretation</strong>: Cars that are heavier and with more horsepower have lower fuel efficiency. These two variables explain most of the variation in <code>mpg</code> in the dataset.</p>
<h3 id="heading-logistic-regression"><strong>Logistic Regression</strong></h3>
<p>You can use logistic regression for binary outcomes, like yes/no questions. For example, predicting whether a vehicle is automatic or manual based on weight and horsepower.</p>
<pre><code class="lang-r">glm_model &lt;- glm(am ~ wt + hp, data = mtcars, family = binomial)
summary(glm_model)
</code></pre>
<p>Lets understand the code</p>
<ul>
<li><p><code>glm()</code> stands for generalized linear model.</p>
</li>
<li><p>The <code>family=binomial</code> option tells R to run logistic regression.</p>
</li>
<li><p>The response variable <code>am</code> indicates transmission type: 0 = automatic, 1 = manual.</p>
</li>
<li><p>Predictor variables remain <code>wt</code> and <code>hp</code>.</p>
</li>
</ul>
<p>Once you run the model, it should look like this in your console:</p>
<pre><code class="lang-r">Call:
glm(formula = am ~ wt + hp, family = binomial, data = mtcars)

Coefficients:
            Estimate Std. Error z value Pr(&gt;|z|)   
(Intercept) <span class="hljs-number">18.86630</span>    <span class="hljs-number">7.44356</span>   <span class="hljs-number">2.535</span>  <span class="hljs-number">0.01126</span> * 
wt          -<span class="hljs-number">8.08348</span>    <span class="hljs-number">3.06868</span>  -<span class="hljs-number">2.634</span>  <span class="hljs-number">0.00843</span> **
hp           <span class="hljs-number">0.03626</span>    <span class="hljs-number">0.01773</span>   <span class="hljs-number">2.044</span>  <span class="hljs-number">0.04091</span> * 
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

(Dispersion parameter <span class="hljs-keyword">for</span> binomial family taken to be <span class="hljs-number">1</span>)

    Null deviance: <span class="hljs-number">43.230</span>  on <span class="hljs-number">31</span>  degrees of freedom
Residual deviance: <span class="hljs-number">10.059</span>  on <span class="hljs-number">29</span>  degrees of freedom
AIC: <span class="hljs-number">16.059</span>

Number of Fisher Scoring iterations: <span class="hljs-number">8</span>
</code></pre>
<p>Here’s an interpreting of the logistic regression model:</p>
<ul>
<li><p>The intercept <code>18.866</code> represents the log-odds of a car being manual when <code>wt=0</code> and <code>hp=0</code>. In other words, when all other variables are <code>0</code>, the baseline log-odds of the outcome is <code>18.866</code>. The intercept is always the baseline value of the outcome when all other variables in the model are zero.</p>
</li>
<li><p>With every additional unit of weight (1000 lbs), the log odds of the car being manual decrease by <code>8.083</code>. This variable strongly affects the probability of the car being manual, as seen with the <code>p-value</code> being <code>0.008</code>, which is statistically significant.</p>
</li>
<li><p>With every additional unit of horsepower, the log odds of the car being manual increase by <code>0.036</code>. This variable also affects the probability of being manual, as seen with the <code>p-value</code> being <code>0.041</code>, which is statistically significant.</p>
</li>
</ul>
<p><strong>Summary of the interpretation</strong>: Heavier cars are more likely to be automatic, while higher horsepower slightly increases the chance of being manual. Together, <code>wt</code> and <code>hp</code> explain a large portion of transmission type variation.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to use R for data analysis, visualization, and statistical modeling, and how to set up your R environment and work with basic data types and data structures.</p>
<p>This article also showed you how to import real-world datasets and explore them using summary statistics. This should help you understand your data before analysis.</p>
<p>Using ggplot2, we visualized the relationships and identified patterns. We built and interpreted a linear regression model to predict fuel efficiency and a logistic regression model to classify transmission type.</p>
<p>You also learned how to interpret coefficients, p-values, and goodness-of-fit measures.</p>
<p>With these skills, you can load datasets, visualize trends, and build simple predictive models in R. Keep practicing with new datasets and explore more advanced techniques to improve your data analysis skills.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn R Programming from Harvard University ]]>
                </title>
                <description>
                    <![CDATA[ Harvard University creates amazing beginner computer science courses. We just released Harvard CS50’s introduction to programming using a language called R, a popular language for statistical computing and graphics in data science and other domains. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-r-programming-from-harvard-university/</link>
                <guid isPermaLink="false">692f65b7eaee334f9337fc73</guid>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 02 Dec 2025 22:18:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764713896891/8c4848e6-27f8-4f1f-aeb5-1c14e1a3ecd6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Harvard University creates amazing beginner computer science courses.</p>
<p>We just released Harvard CS50’s introduction to programming using a language called R, a popular language for statistical computing and graphics in data science and other domains. Carter Zenke developed this course.</p>
<p>Learn to use RStudio, a popular integrated development environment (IDE). Learn to represent real-world data with vectors, matrices, arrays, lists, and data frames. Filter data with conditions, via which you can analyze subsets of data. Apply functions and loops, via which you can manipulate and summarize data sets. Write functions to modularize code and raise exceptions when something goes wrong. Tidy data with R’s tidyverse and create colorful visualizations with R’s grammar of graphics. By course’s end, learn to package, test, and share R code for others to use. Assignments inspired by real-world data sets.</p>
<p>Here are the sections in this course:</p>
<ul>
<li><p>Introduction</p>
</li>
<li><p>Representing Data</p>
</li>
<li><p>Transforming Data</p>
</li>
<li><p>Applying Functions</p>
</li>
<li><p>Tidying Data</p>
</li>
<li><p>Visualizing Data</p>
</li>
<li><p>Testing Programs</p>
</li>
<li><p>Packaging Programs</p>
</li>
</ul>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/g_3IKHG-rfA">the freeCodeCamp.org YouTube channel</a> (9-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/g_3IKHG-rfA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Local RAG App with Ollama and ChromaDB in the R Programming Language ]]>
                </title>
                <description>
                    <![CDATA[ A Large Language Model (LLM) is a type of machine learning model that is trained to understand and generate human-like text. These models are trained on vast datasets to capture the nuances of human language, enabling them to generate coherent and co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-local-rag-app-with-ollama-and-chromadb-in-r/</link>
                <guid isPermaLink="false">67fd5ac89a2c2895da61d799</guid>
                
                    <category>
                        <![CDATA[ ollama ]]>
                    </category>
                
                    <category>
                        <![CDATA[ chromadb ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ RAG  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elabonga Atuo ]]>
                </dc:creator>
                <pubDate>Mon, 14 Apr 2025 18:58:16 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744638731389/83993a5e-7a4d-4615-a8c5-582008115fc4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A Large Language Model (LLM) is a type of machine learning model that is trained to understand and generate human-like text. These models are trained on vast datasets to capture the nuances of human language, enabling them to generate coherent and contextually relevant responses.</p>
<p>You can enhance the performance of an LLM by providing context — structured or unstructured data, such as documents, articles, or knowledge bases — tailored to the domain or information you want the model to specialize in. Using techniques like prompt engineering and context injection, you can build an intelligent chatbot capable of navigating extensive datasets, retrieving relevant information, and delivering responses.</p>
<p>Whether it's storing recipes, code documentation, research articles, or answering domain-specific queries, an LLM-based chatbot can adapt to your needs with customization and privacy. You can deploy it locally to create a highly specialized conversational assistant that respects your data.</p>
<p>In this article, you will learn how to build a local Retrieval-Augmented Generation (RAG) application using Ollama and ChromaDB in R. By the end, you'll have a custom conversational assistant with a Shiny interface that efficiently retrieves information while maintaining privacy and customization.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-rag">What is RAG?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-overview">Project Overview</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ollama-installation">Ollama Installation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-collection-and-cleaning">Data Collection and Cleaning</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-chunks">How to Create Chunks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-generate-sentence-embeddings">How to Generate Sentence Embeddings</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-vector-database-for-embedding-storage">How to Set Up the Vector Database for Embedding Storage</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-write-the-user-input-query-embedding-function">How to Write the User Input Query Embedding Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tool-calling">Tool Calling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-initialize-the-chat-system-design-prompts-and-integrate-tools">How to Initialize the Chat System, Design Prompts, and Integrate Tools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-interact-with-your-chatbot-using-a-shiny-app">How to Interact with Your Chatbot Using a Shiny App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-complete-code">Complete Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-rag">What is RAG?</h2>
<p>Retrieval-Augmented Generation (RAG) is a method that integrates retrieval systems with generative AI, enabling chatbots to access recent and specific information from external sources.</p>
<p>By using a retrieval pipeline, the chatbot can fetch up-to-date, relevant data and combine it with the generative model’s language capabilities, producing responses that are both accurate and contextually enriched. This makes RAG particularly useful for applications requiring fact-based, real-time knowledge delivery.</p>
<h2 id="heading-project-overview">Project Overview</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744367291671/3e7989f8-0cd9-4857-ba48-23a352d9ae8d.png" alt="Setting up a local RAG chatbot from data gathering, cleaning, chunking, embedding, vector database storage, system prompting and interactive chatbot using Shiny" class="image--center mx-auto" width="1318" height="1101" loading="lazy"></p>
<h2 id="heading-project-setup">Project Setup</h2>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before you begin, ensure you have installed the latest version of the items listed here:</p>
<ol>
<li><p><a target="_blank" href="https://posit.co/download/rstudio-desktop/"><strong>RStudio</strong></a><strong>: The IDE</strong> <em>–</em> RStudio is the primary workspace where you'll write and test your R code. Its user-friendly interface, debugging tools, and integrated environment make it ideal for data analysis and chatbot development.</p>
</li>
<li><p><a target="_blank" href="https://cran.rstudio.com/"><strong>R</strong></a><strong>: The Programming Language</strong> <em>–</em> R is the backbone of your project. You'll use it to handle data manipulation, apply statistical models, and integrate your recipe chatbot components seamlessly.</p>
</li>
<li><p><a target="_blank" href="https://www.python.org/downloads/"><strong>Python</strong></a> – Some libraries, like the embedding library you'll use for text vectorization, are built on Python. It’s vital to have Python installed to enable these functionalities alongside your R code.</p>
</li>
<li><p><a target="_blank" href="https://www.java.com/en/download/"><strong>Java</strong></a> – Java serves as a foundational element for certain embedding libraries. It ensures efficient processing and compatibility for text embedding tasks required to train your chatbot.</p>
</li>
<li><p><a target="_blank" href="https://www.docker.com/products/docker-desktop/"><strong>Docker Desktop</strong></a> – Docker Desktop allows you to run ChromaDB, the vector database, locally on your machine. This enables fast and reliable storage of embeddings, ensuring your chatbot retrieves relevant information quickly.</p>
</li>
<li><p><a target="_blank" href="https://ollama.com/"><strong>Ollama</strong></a> – Ollama brings powerful Large Language Models (LLMs) directly to your local computer, removing the need for cloud resources. It lets you access multiple models, customize outputs, and integrate them into your chatbot effortlessly.</p>
</li>
</ol>
<h2 id="heading-ollama-installation">Ollama Installation</h2>
<p>Ollama is an open-sourced tool you can use to run and manage LLMs on your computer. Once installed, you can access various LLMs as per your needs. You will be using <code>llama3.2:3b-instruct-q4_K_M</code> model to build this chatbot.</p>
<p>A quantized model is a version of a machine learning model that has been optimized to use less memory and computational power by reducing the precision of the numbers it uses. This enables you to use an LLM locally, especially when you don’t have access to a GPU (Graphics Processing Unit – a specialized processor that perform complex computations).</p>
<p>To start, you can download and install the Ollama software <a target="_blank" href="https://ollama.com/download">here</a>.</p>
<p>Then you can confirm installation by running this command:</p>
<pre><code class="lang-bash">ollama --version
</code></pre>
<p>Run the following command to start Ollama:</p>
<pre><code class="lang-bash">ollama serve
</code></pre>
<p>Next, run the following command to pull the Q4_K_M quantization of llama3.2:3b-instruct:</p>
<pre><code class="lang-bash">ollama pull llama3.2:3b-instruct-q4_K_M
</code></pre>
<p>Then confirm that the model was extracted with this:</p>
<pre><code class="lang-bash">ollama list
</code></pre>
<p>If the model extraction was successful, a list containing the model’s name, ID, and size will be returned, like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744288047721/f6349ca4-fe86-4851-beaf-2f04fe2a4d80.png" alt="Confirm Ollama Installation" class="image--center mx-auto" width="1455" height="256" loading="lazy"></p>
<p>Now you can chat with the model:</p>
<pre><code class="lang-bash">ollama run llama3.2:3b-instruct-q4_K_M
</code></pre>
<p>If successful, you should receive a prompt that you can test by asking a question and getting an answer. For example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744288433940/d831d256-0f6c-49c0-b647-bce1c1976584.png" alt="Ollama llama3.2:3b-instruct-q4_K_M chat console" class="image--center mx-auto" width="1612" height="559" loading="lazy"></p>
<p>Then you can exit the console by typing <code>/bye</code> or ctrl + D</p>
<h2 id="heading-data-collection-and-cleaning">Data Collection and Cleaning</h2>
<p>The chatbot you are building will be a cooking assistant that suggests recipes given your available ingredients, what you want to eat, and how much food a recipe yields.</p>
<p>You first have to get the data to train the model. You will be using a <a target="_blank" href="https://www.kaggle.com/datasets/paultimothymooney/recipenlg">dataset</a> that contains recipes from Kaggle.</p>
<p>To start, load the necessary libraries:</p>
<pre><code class="lang-r"><span class="hljs-comment"># loading required libraries</span>
<span class="hljs-keyword">library</span>(xml2) <span class="hljs-comment">#read, parse, and manipulate XML,HTML documents</span>
<span class="hljs-keyword">library</span>(jsonlite) <span class="hljs-comment">#manipulate JSON objects</span>

<span class="hljs-keyword">library</span>(RKaggle) <span class="hljs-comment"># download datasets from Kaggle </span>
<span class="hljs-keyword">library</span>(dplyr)   <span class="hljs-comment"># data manipulation</span>
</code></pre>
<p>Then download and save recipe dataset:</p>
<pre><code class="lang-r"><span class="hljs-comment"># Download and read the "recipe" dataset from Kaggle</span>
recipes_list &lt;- RKaggle::get_dataset(<span class="hljs-string">"thedevastator/better-recipes-for-a-better-life"</span>)
</code></pre>
<p>Inspect the dataframe and extract the first element like this:</p>
<pre><code class="lang-r"><span class="hljs-comment"># inspect the dataset</span>
class(recipes_list)
str(recipes_list)
head(recipes_list)
<span class="hljs-comment"># extract the first tibble</span>
recipes_df &lt;- recipes_list[[<span class="hljs-number">1</span>]]
</code></pre>
<p>A quick inspection of the <code>recipes_list</code> object shows that it contains two objects of type tibble. You will be using only the first element for this project. A tibble is a type of data structure used for storing and manipulating data. It’s similar to a traditional dataframe, but it’s designed to enforce stricter rules and perform fewer automatic actions compared to traditional dataframes.</p>
<p>We’ll use a regular dataframe in this project because more people are likely familiar with it. It can also efficiently handle row indexing, which is crucial for accessing and manipulating specific rows in our recipe dataset.</p>
<p>In the code block below, you’ll convert the tibble to a dataframe and then drop the first column, which is the index column. Then you’ll inspect the newly converted dataframe and drop unnecessary columns.</p>
<p>Unnecessary columns are best removed to streamline the dataset and focus on relevant features. In this project, we’ll drop certain columns that aren’t particularly useful for training the chatbot. This ensures that the model concentrates on meaningful data to improve its accuracy and functionality.</p>
<pre><code class="lang-r"><span class="hljs-comment"># convert to dataframe and drop the first column</span>
recipes_df &lt;- as.data.frame(recipes_df[, -<span class="hljs-number">1</span>])
<span class="hljs-comment"># inspect the converted dataframe</span>
head(recipes_df)
class(recipes_df)
colnames(recipes_df)
<span class="hljs-comment"># drop unnecessary columns</span>
cleaned_recipes_df &lt;- subset(recipes_df, select = -c(yield,rating,url,cuisine_path,nutrition,timing,img_src))
</code></pre>
<p>Now you need to identify rows with NA (missing) values, which you can do like this:</p>
<pre><code class="lang-r"><span class="hljs-comment"># Identify rows and columns with NA values</span>
which(is.na(cleaned_recipes_df), arr.ind = <span class="hljs-literal">TRUE</span>)

<span class="hljs-comment"># a quick inspection reveals columns [2:4] have missing values</span>
subset_column_names &lt;- colnames(cleaned_recipes_df)[<span class="hljs-number">2</span>:<span class="hljs-number">4</span>]
subset_column_names
</code></pre>
<p>It is important to handle NA values to ensure that your data is complete, to prevent errors, and to preserve context.</p>
<p>Now, replace the NA values and confirm that there are no missing values:</p>
<pre><code class="lang-r"><span class="hljs-comment"># Replace NA values dynamically based on conditions</span>
cols_to_modify &lt;- c(<span class="hljs-string">"prep_time"</span>, <span class="hljs-string">"cook_time"</span>, <span class="hljs-string">"total_time"</span>)
cleaned_recipes_df[cols_to_modify] &lt;- lapply(
  cleaned_recipes_df[cols_to_modify],
  <span class="hljs-keyword">function</span>(x, df) {
    <span class="hljs-comment"># Replace NA in prep_time and cook_time where both are NA</span>
    replace(x, is.na(df$prep_time) &amp; is.na(df$cook_time), <span class="hljs-string">"unknown"</span>)
  },
  df = cleaned_recipes_df  <span class="hljs-comment"># Pass the whole dataframe for conditions</span>
)
cleaned_recipes_df &lt;- cleaned_recipes_df %&gt;%
  mutate(
    prep_time = case_when(
      <span class="hljs-comment"># If cooktime is present but preptime is NA, replace with "no preparation required"</span>
      !is.na(cook_time) &amp; is.na(prep_time) ~ <span class="hljs-string">"no preparation required"</span>,
      <span class="hljs-comment"># Otherwise, retain original value</span>
      <span class="hljs-literal">TRUE</span> ~ as.character(prep_time)
    ),
    cook_time = case_when(
      <span class="hljs-comment"># If prep_time is present but cook_time is NA, replace with "no cooking required"</span>
      !is.na(prep_time) &amp; is.na(cook_time) ~ <span class="hljs-string">"no cooking required"</span>,
      <span class="hljs-comment"># Otherwise, retain original value</span>
      <span class="hljs-literal">TRUE</span> ~ as.character(cook_time)
    )
  )
<span class="hljs-comment"># confirm there are no missing values</span>
any(is.na(cleaned_recipes_df))
)

<span class="hljs-comment"># confirm the replacing NA logic works by inspecting specific rows</span>
cleaned_recipes_df[<span class="hljs-number">1081</span>,]
cleaned_recipes_df[<span class="hljs-number">1</span>,]
cleaned_recipes_df[<span class="hljs-number">405</span>,]
</code></pre>
<p>For this tutorial, we’ll subset the dataframe to the first 250 rows for demo purposes. This saves on time when it comes to generating embeddings.</p>
<pre><code class="lang-r"><span class="hljs-comment"># recommended for demo/learning purposes</span>
cleaned_recipes_df &lt;- head(cleaned_recipes_df,<span class="hljs-number">250</span>)
</code></pre>
<h2 id="heading-how-to-create-chunks">How to Create Chunks</h2>
<p>To understand why chunking is important before embedding, you need to understand what an embedding is.</p>
<p>An embedding is a vectoral representation of a word or a sentence. Machines don’t understand human text – they understand numbers. LLMs work by transforming human text to numerical representations in order to give answers. The process of generating embeddings requires a lot of computation, and breaking down the data to be embedded optimizes the embedding process.</p>
<p>So now we’re going to split the dataframe into smaller chunks of a specified size to enable efficient batch processing and iteration.</p>
<pre><code class="lang-r"><span class="hljs-comment"># Define the size of each chunk (number of rows per chunk)</span>
chunk_size &lt;- <span class="hljs-number">1</span>

<span class="hljs-comment"># Get the total number of rows in the dataframe</span>
n &lt;- nrow(cleaned_recipes_df)

<span class="hljs-comment"># Create a vector of group numbers for chunking</span>
<span class="hljs-comment"># Each group number repeats for 'chunk_size' rows</span>
<span class="hljs-comment"># Ensure the vector matches the total number of rows</span>
r &lt;- rep(<span class="hljs-number">1</span>:ceiling(n/chunk_size), each = chunk_size)[<span class="hljs-number">1</span>:n]

<span class="hljs-comment"># Split the dataframe into smaller chunks (subsets) based on the group numbers</span>
chunks &lt;- split(cleaned_recipes_df, r)
</code></pre>
<h2 id="heading-how-to-generate-sentence-embeddings">How to Generate Sentence Embeddings</h2>
<p>As previously mentioned, embeddings are vector representations of words or sentences. Embeddings can be generated from both words and sentences. How you choose to generate embeddings depends on your intended application of the LLM.</p>
<p>Word embeddings are numerical representations of individual words in a continuous vector space. They capture semantic relationships between words, allowing similar words to have vectors close to each other.</p>
<p>Word embeddings can be used in search engines as they support word-level queries by matching embeddings to retrieve relevant documents. They can also be used in text classification to classify documents, emails, or tweets based on word-level features (for example, detecting spam emails or sentiment analysis).</p>
<p>Sentence embeddings are numerical representations of entire sentences in a vector space, designed to capture the overall meaning and context of the sentence. They are used in settings where sentences provide better context like question answering systems where user queries are matched to relevant sentences or documents for more precise retrieval.</p>
<p>For our recipe chatbot, sentence embedding is the best choice.</p>
<p>First, create an empty dataframe that has three columns.</p>
<pre><code class="lang-r"><span class="hljs-comment">#empty dataframe</span>
recipe_sentence_embeddings &lt;-  data.frame(
  recipe = character(),
  recipe_vec_embeddings = I(list()),
  recipe_id = character()
)
</code></pre>
<p>The first column will hold the actual recipe in text form, the <code>recipe_vec_embeddings</code> column will hold the generated sentence embeddings, and the <code>recipe_id</code> holds a unique id for each recipe. This will help in indexing and retrieval from the vector database.</p>
<p>Next, it’s helpful to define a progress bar, which you can do like this:</p>
<pre><code class="lang-r"><span class="hljs-comment"># create a progress bar</span>
pb &lt;- txtProgressBar(min = <span class="hljs-number">1</span>, max = length(chunks), style = <span class="hljs-number">3</span>)
</code></pre>
<p>Embedding can take a while, so it’s important to keep track of the progress of the process.</p>
<p>Now it’s time to generate embeddings and populate the dataframe.</p>
<p>Write a for loop that executes the code block as long as the length of the chunks.</p>
<pre><code class="lang-r"><span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(chunks)) {}
</code></pre>
<p>The recipe field is the text at the chunk that is currently being executed and the unique chunk id is generated by pasting the index of the chunk and the text “chunk”.</p>
<pre><code class="lang-r"><span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(chunks)) {
    recipe &lt;- as.character(chunks[i])
    recipe_id &lt;- paste0(<span class="hljs-string">"recipe"</span>,i)
}
</code></pre>
<p>The text embed function from the text library generates either sentence or word embeddings. It takes in a character variable or a dataframe and produces a tibble of embeddings. You can read loading instructions here for smooth running of the <a target="_blank" href="https://www.r-text.org/">text</a> library.</p>
<p>The <code>batch_size</code> defines how many rows are embedded at a time from the input. Setting the <code>keep_token_embeddings</code> discards the embeddings for individual tokens after processing, and <code>aggregation_from_layers_to_tokens</code> “concatenates” or combines embeddings from specified layers to create detailed embeddings for each token. A token is the smallest unit of text that a model can process.</p>
<pre><code class="lang-r"><span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(chunks)) {
    recipe &lt;- as.character(chunks[i])
    recipe_id &lt;- paste0(<span class="hljs-string">"recipe"</span>,i)
    recipe_embeddings &lt;- textEmbed(as.character(recipe),
                                layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                keep_token_embeddings = <span class="hljs-literal">FALSE</span>,
                                batch_size = <span class="hljs-number">1</span>
  )
}
</code></pre>
<p>In order to specify sentence embeddings, you need to set the argument to the <code>aggregation_from_tokens_to_texts</code> parameter as <code>"mean"</code>.</p>
<pre><code class="lang-r">aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>
</code></pre>
<p>The "mean" operation averages the embeddings of all tokens in a sentence to generate a single vector that represents the entire sentence. This sentence-level embedding captures the overall meaning and semantics of the text, regardless of its token length.</p>
<pre><code class="lang-r"><span class="hljs-comment"># convert tibble to vector</span>
  recipe_vec_embeddings &lt;- unlist(recipe_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
  recipe_vec_embeddings &lt;- list(recipe_vec_embeddings)
</code></pre>
<p>The embedding function returns a tibble object. In order to obtain a vector embedding, you need to first unlist the tibble and drop the row names and then list the result to form a simple vector.</p>
<pre><code class="lang-r">  <span class="hljs-comment"># Append the current chunk's data to the dataframe</span>
  recipe_sentence_embeddings &lt;- recipe_sentence_embeddings %&gt;%
    add_row(
      recipe = recipe,
      recipe_vec_embeddings = recipe_vec_embeddings,
      recipe_id = recipe_id
    )
</code></pre>
<p>Finally, update the empty dataframe after each iteration with the newly generated data.</p>
<pre><code class="lang-r">  <span class="hljs-comment"># track embedding progress</span>
  setTxtProgressBar(pb, i)
</code></pre>
<p>In order to keep track of the embedding progress, you can use the earlier defined progress bar inside the loop. It will update at the end of every iteration.</p>
<p><strong>Complete Code Block:</strong></p>
<pre><code class="lang-r"><span class="hljs-comment"># load required library</span>
<span class="hljs-keyword">library</span>(text)
<span class="hljs-comment"># # ensure to read loading instructions here for smooth running of the 'text' library</span>
<span class="hljs-comment"># # https://www.r-text.org/</span>
<span class="hljs-comment"># embedding data</span>
<span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(chunks)) {
  recipe &lt;- as.character(chunks[i])
  recipe_id &lt;- paste0(<span class="hljs-string">"recipe"</span>,i)
  recipe_embeddings &lt;- textEmbed(as.character(recipe),
                                layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                keep_token_embeddings = <span class="hljs-literal">FALSE</span>,
                                batch_size = <span class="hljs-number">1</span>
  )

  <span class="hljs-comment"># convert tibble to vector</span>
  recipe_vec_embeddings &lt;- unlist(recipe_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
  recipe_vec_embeddings &lt;- list(recipe_vec_embeddings)

  <span class="hljs-comment"># Append the current chunk's data to the dataframe</span>
  recipe_sentence_embeddings &lt;- recipe_sentence_embeddings %&gt;%
    add_row(
      recipe = recipe,
      recipe_vec_embeddings = recipe_vec_embeddings,
      recipe_id = recipe_id
    )

  <span class="hljs-comment"># track embedding progress</span>
  setTxtProgressBar(pb, i)

}
</code></pre>
<h2 id="heading-how-to-set-up-the-vector-database-for-embedding-storage">How to Set Up the Vector Database for Embedding Storage</h2>
<p>A vector database is a special type of database that stores embeddings and allows you to query and retrieve relevant information. There are numerous vector databases available, but for this project, you will use ChromaDB, an open-source option that integrates with the R environment through the <code>rchroma</code> library.</p>
<p>ChromaDB runs locally in a Docker container. Just make sure you have Docker installed and running on your device.</p>
<p>Then load the rchroma library and run your ChromaDB instance:</p>
<pre><code class="lang-r"><span class="hljs-comment"># load rchroma library</span>
<span class="hljs-keyword">library</span>(rchroma)
<span class="hljs-comment"># run ChromaDB instance.</span>
chroma_docker_run()
</code></pre>
<p>If it was successful, you should see this in the console:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744383249217/bd8fb67c-0731-46f9-8a13-0747b4789714.png" alt="Confirm ChromaDB is running locally" class="image--center mx-auto" width="598" height="121" loading="lazy"></p>
<p>Next, connect to a local ChromaDB instance and check the connection:</p>
<pre><code class="lang-r"><span class="hljs-comment"># Connect to a local ChromaDB instance</span>
client &lt;- chroma_connect()

<span class="hljs-comment"># Check the connection</span>
heartbeat(client)
version(client)
</code></pre>
<p>Now you’ll need to create a collection and confirm that it was created. Collections in ChromaDB function similarly to tables in conventional databases.</p>
<pre><code class="lang-r"><span class="hljs-comment"># Create a new collection</span>
create_collection(client, <span class="hljs-string">"recipes_collection"</span>)

<span class="hljs-comment"># List all collections</span>
list_collections(client)
</code></pre>
<p>Now, add embeddings to the collection. To add embeddings to the <code>recipes_collection</code>, use the <code>add_documents</code> function.</p>
<pre><code class="lang-r"><span class="hljs-comment"># Add documents to the collection</span>
add_documents(
  client,
  <span class="hljs-string">"recipes_collection"</span>,
  documents = recipe_sentence_embeddings$recipe,
  ids = recipe_sentence_embeddings$recipe_id,
  embeddings = recipe_sentence_embeddings$recipe_vec_embeddings
)
</code></pre>
<p>The <code>add_documents()</code> function is used to add recipe data to the <code>recipes_collection</code>. Here's a breakdown of its arguments and how the corresponding data is accessed:</p>
<ol>
<li><p><code>documents</code>: This argument represents the recipe text. It is sourced from the <code>recipe</code> column of the <code>recipe_sentence_embeddings</code> dataframe.</p>
</li>
<li><p><code>ids</code>: This is the unique identifier for each recipe. It is extracted from the <code>recipe_id</code> column of the same dataframe.</p>
</li>
<li><p><code>embeddings</code>: This contains the sentence embeddings, which were previously generated for each recipe. These embeddings are accessed from the <code>recipe_vec_embeddings</code> column of the dataframe.</p>
</li>
</ol>
<p>All three arguments—<code>documents</code>, <code>ids</code>, and <code>embeddings</code>—are obtained by subsetting their respective columns from the <code>recipe_sentence_embeddings</code> dataframe.</p>
<h2 id="heading-how-to-write-the-user-input-query-embedding-function">How to Write the User Input Query Embedding Function</h2>
<p>In order to retrieve information from a vector database, you must first embed your query text. The database compares your query's embedding with its stored embeddings to find and retrieve the most relevant document.</p>
<p>It's important to ensure that the dimensions (rows × columns) of your query embedding match those of the database embeddings. This alignment is achieved by using the same embedding model to generate your query.</p>
<p>Matching embeddings involves calculating the similarity (for example, cosine similarity) between the query and stored embeddings, identifying the closest match for effective retrieval.</p>
<p>Let’s write a function that allows us to embed a query which then queries similar documents using the generated embeddings. Wrapping it in a function makes it reusable.</p>
<pre><code class="lang-r">  <span class="hljs-comment">#sentence embeddings function and query</span>
  question &lt;- <span class="hljs-keyword">function</span>(sentence){
    sentence_embeddings &lt;- textEmbed(sentence,
                                     layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                     aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                     aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                     keep_token_embeddings = <span class="hljs-literal">FALSE</span>
    )

    <span class="hljs-comment"># convert tibble to vector</span>
    sentence_vec_embeddings &lt;- unlist(sentence_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
    sentence_vec_embeddings &lt;- list(sentence_vec_embeddings)

    <span class="hljs-comment"># Query similar documents using embeddings</span>
    results &lt;- query(
      client,
      <span class="hljs-string">"recipes_collection"</span>,
      query_embeddings = sentence_vec_embeddings ,
      n_results = <span class="hljs-number">2</span>
    )
    results

  }
</code></pre>
<p>This chunk of code is similar to how we have previously used the <code>text_embed()</code> function. The <code>query()</code> function is added to enable querying the vector database, particularly the recipes' collection, and returns the top two documents that closely match a user’s query.</p>
<p>Our function thus takes in a sentence as an argument and embeds the sentence to generate sentence embeddings. It then queries the database and returns two documents that match the query most.</p>
<h2 id="heading-tool-calling">Tool Calling</h2>
<p>To interact with Ollama in R, you will utilize the <code>ellmer</code> library. This library streamlines the use of large language models (LLMs) by offering an interface that enables seamless access to and interaction with a variety of LLM providers.</p>
<p>To enhance the LLM’s usage, we need to provide context to it. You can do this by tool calling. Tool calling allows an LLM to access external resources in order to enhance its functionality.</p>
<p>For this project, we are implementing <a target="_blank" href="https://www.freecodecamp.org/news/learn-rag-fundamentals-and-advanced-techniques/">Retrieval-Augmented Generation (RAG)</a>, which combines retrieving relevant information from a vector database and generating responses using an LLM. This approach improves the chatbot's ability to provide accurate and contextually relevant answers.</p>
<p>Now, define a function that links to the LLM to provide context using the <code>tool()</code> function from the <code>ellmer</code> library.</p>
<pre><code class="lang-r"><span class="hljs-comment"># load ellmer library</span>
<span class="hljs-keyword">library</span>(ellmer)

<span class="hljs-comment"># function that links to llm to provide context</span>
  tool_context  &lt;- tool(
    question,
    <span class="hljs-string">"obtains the right context for a given question"</span>,
    sentence = type_string()

  )
</code></pre>
<p>The <code>tool()</code> function takes the question function that returns the relevant documents that we’ll use as context as the first argument. We’ll use the documents to help the LLM answer questions accordingly.</p>
<p>The text, "obtains the right context for a given question", is a description of what the tool will be doing.</p>
<p>Finally, the <code>sentence = type_string()</code> defines what type of object the <code>question()</code> function expects.</p>
<h2 id="heading-how-to-initialize-the-chat-system-design-prompts-and-integrate-tools">How to Initialize the Chat System, Design Prompts, and Integrate Tools</h2>
<p>Next, you’ll set up a conversational AI system by defining its role and functionality. Using system prompt design, you will shape the assistant’s behavior, tone, and focus as a culinary assistant. You’ll also integrate external tools to extend the chatbot’s capabilities by registering tools. Let’s dive in.</p>
<p>First, you need to initialize a Chat Object:</p>
<pre><code class="lang-r"><span class="hljs-comment">#  Initialize the chat system with propmpt instructions.</span>
  chat &lt;- chat_ollama(system_prompt = <span class="hljs-string">"You are a knowledgeable culinary assistant specializing in recipe recommendations. 
                      You provide tailored meal suggestions based on the user's available ingredients and the desired amount of food or servings.
                      Ensure the recipes align closely with the user's inputs and yield the expected quantity."</span>,
                      model = <span class="hljs-string">"llama3.2:3b-instruct-q4_K_M"</span>)
</code></pre>
<p>You can do that using the <code>chat_ollama()</code> function. This sets up a conversational agent with the specified system prompt and model.</p>
<p>The system prompt defines the conversational behavior, tone, and focus of the LLM while the model argument specifies the language model (<code>llama3.2:3b-instruct-q4_K_M</code>) that the chat system will use to generate responses.</p>
<p>Next, you need to register a tool.</p>
<pre><code class="lang-r"> <span class="hljs-comment">#register tool</span>
  chat$register_tool(tool_context)
</code></pre>
<p>We need to tell our chat object about our <code>tool_context()</code> function. Do this by registering a tool using the <code>register_tool()</code> function.</p>
<h2 id="heading-how-to-interact-with-your-chatbot-using-a-shiny-app"><strong>How to Interact with Your Chatbot Using a Shiny App</strong></h2>
<p>To interact with the chatbot you’ve just created, we’ll use <strong>Shiny</strong>, a framework for building interactive web applications in R. Shiny provides a user-friendly graphical interface that allows seamless interaction with the chatbot.</p>
<p>For this purpose, we’ll use the <strong>shinychat</strong> library, which simplifies the process of building a chat interface within a Shiny app. This involves defining two key components:</p>
<ol>
<li><p><strong>User Interface (UI)</strong>:</p>
<ul>
<li><p>Responsible for the visual layout and what the user sees.</p>
</li>
<li><p>In this case, <code>chat_ui("chat")</code> is used to create the interactive chat interface.</p>
</li>
</ul>
</li>
<li><p><strong>Server Function</strong>:</p>
<ul>
<li><p>Handles the functionality and logic of the application.</p>
</li>
<li><p>It connects the chatbot to external tools and manages processes like embedding queries, retrieving relevant responses, and handling user inputs.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-r"><span class="hljs-comment"># load the required library</span>
<span class="hljs-keyword">library</span>(shinychat)

<span class="hljs-comment"># wrap the chat code in a Shiny App</span>
ui &lt;- bslib::page_fluid(
  chat_ui(<span class="hljs-string">"chat"</span>)
)

server &lt;- <span class="hljs-keyword">function</span>(input, output, session) {
  <span class="hljs-comment"># Connect to a local ChromaDB instance running on docker with embeddings loaded</span>
  client &lt;- chroma_connect()

  <span class="hljs-comment">#sentence embeddings function and query</span>
  question &lt;- <span class="hljs-keyword">function</span>(sentence){
    sentence_embeddings &lt;- textEmbed(sentence,
                                     layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                     aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                     aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                     keep_token_embeddings = <span class="hljs-literal">FALSE</span>
    )

    <span class="hljs-comment"># convert tibble to vector</span>
    sentence_vec_embeddings &lt;- unlist(sentence_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
    sentence_vec_embeddings &lt;- list(sentence_vec_embeddings)

    <span class="hljs-comment"># Query similar documents using embeddings</span>
    results &lt;- query(
      client,
      <span class="hljs-string">"recipes_collection"</span>,
      query_embeddings = sentence_vec_embeddings ,
      n_results = <span class="hljs-number">2</span>
    )
    results

  }


  <span class="hljs-comment"># function that provides context</span>
  tool_context  &lt;- tool(
    question,
    <span class="hljs-string">"obtains the right context for a given question"</span>,
    sentence = type_string()

  )

  <span class="hljs-comment">#  Initialize the chat system with the first chunk</span>
  chat &lt;- chat_ollama(system_prompt = <span class="hljs-string">"You are a knowledgeable culinary assistant specializing in recipe recommendations. 
                      You provide tailored meal suggestions based on the user's available ingredients and the desired amount of food or servings.
                      Ensure the recipes align closely with the user's inputs and yield the expected quantity."</span>,
                      model = <span class="hljs-string">"llama3.2:3b-instruct-q4_K_M"</span>)
  <span class="hljs-comment">#register tool</span>
  chat$register_tool(tool_context)

  observeEvent(input$chat_user_input, {
    stream &lt;- chat$stream_async(input$chat_user_input)
    chat_append(<span class="hljs-string">"chat"</span>, stream)
  })
}

shinyApp(ui, server)
</code></pre>
<p>Alright, let’s understand how this is working:</p>
<ol>
<li><p><strong>User input monitoring with</strong> <code>observeEvent()</code>: The <code>observeEvent()</code> block monitors user inputs from the chat interface (<code>input$chat_user_input</code>). When a user sends a message, the chatbot processes it, retrieves relevant context using the embeddings, and streams the response dynamically to the chat interface.</p>
</li>
<li><p><strong>Tool calling for context</strong>: The chatbot employs tool calling to interact with external resources (like the vector database) and enhance its functionality. In this project, Retrieval-Augmented Generation (RAG) ensures the chatbot provides accurate and context-rich responses by integrating retrieval and generation seamlessly.</p>
</li>
</ol>
<p>This approach brings the chatbot to life, enabling users to interact with it dynamically through a responsive Shiny app.</p>
<h2 id="heading-complete-code">Complete Code</h2>
<p>The R scripts have been split in two, with <code>data.R</code> containing code that handles data gathering and cleaning, text chunking, sentence embeddings generation, creating a vector database, and loading documents to it.</p>
<p>The <code>chat.R</code> script contains code that handles user input querying, context retrieval, chat initialization, system prompt design, tool integration, and a chat Shiny app.</p>
<p><strong>data.R</strong></p>
<pre><code class="lang-r"><span class="hljs-comment"># install and load required packages</span>
<span class="hljs-comment"># install devtools from CRAN</span>
install.packages(<span class="hljs-string">'devtools'</span>)
devtools::install_github(<span class="hljs-string">"benyamindsmith/RKaggle"</span>)

<span class="hljs-keyword">library</span>(text)
<span class="hljs-keyword">library</span>(rchroma)
<span class="hljs-keyword">library</span>(RKaggle)
<span class="hljs-keyword">library</span>(dplyr)

<span class="hljs-comment"># run ChromaDB instance.</span>
chroma_docker_run()

<span class="hljs-comment"># Connect to a local ChromaDB instance</span>
client &lt;- chroma_connect()

<span class="hljs-comment"># Check the connection</span>
heartbeat(client)
version(client)


<span class="hljs-comment"># Create a new collection</span>
create_collection(client, <span class="hljs-string">"recipes_collection"</span>)

<span class="hljs-comment"># List all collections</span>
list_collections(client)

<span class="hljs-comment"># Download and read the "recipe" dataset from Kaggle</span>
recipes_list &lt;- RKaggle::get_dataset(<span class="hljs-string">"thedevastator/better-recipes-for-a-better-life"</span>)

<span class="hljs-comment"># extract the first tibble</span>
recipes_df &lt;- recipes_list[[<span class="hljs-number">1</span>]]

<span class="hljs-comment"># convert to dataframe and drop the first column</span>
recipes_df &lt;- as.data.frame(recipes_df[, -<span class="hljs-number">1</span>])

<span class="hljs-comment"># drop unnecessary columns</span>
cleaned_recipes_df &lt;- subset(recipes_df, select = -c(yield,rating,url,cuisine_path,nutrition,timing,img_src))

<span class="hljs-comment">## Replace NA values dynamically based on conditions</span>
<span class="hljs-comment"># Replace NA when all columns have NA values</span>
cols_to_modify &lt;- c(<span class="hljs-string">"prep_time"</span>, <span class="hljs-string">"cook_time"</span>, <span class="hljs-string">"total_time"</span>)
cleaned_recipes_df[cols_to_modify] &lt;- lapply(
  cleaned_recipes_df[cols_to_modify],
  <span class="hljs-keyword">function</span>(x, df) {
    <span class="hljs-comment"># Replace NA in prep_time and cook_time where both are NA</span>
    replace(x, is.na(df$prep_time) &amp; is.na(df$cook_time), <span class="hljs-string">"unknown"</span>)
  },
  df = cleaned_recipes_df  
)

<span class="hljs-comment"># Replace NA when either or columns have NA values</span>
cleaned_recipes_df &lt;- cleaned_recipes_df %&gt;%
  mutate(
    prep_time = case_when(
      <span class="hljs-comment"># If cook_time is present but prep_time is NA, replace with "no preparation required"</span>
      !is.na(cook_time) &amp; is.na(prep_time) ~ <span class="hljs-string">"no preparation required"</span>,
      <span class="hljs-comment"># Otherwise, retain original value</span>
      <span class="hljs-literal">TRUE</span> ~ as.character(prep_time)
    ),
    cook_time = case_when(
      <span class="hljs-comment"># If prep_time is present but cook_time is NA, replace with "no cooking required"</span>
      !is.na(prep_time) &amp; is.na(cook_time) ~ <span class="hljs-string">"no cooking required"</span>,
      <span class="hljs-comment"># Otherwise, retain original value</span>
      <span class="hljs-literal">TRUE</span> ~ as.character(cook_time)
    )
  )

<span class="hljs-comment"># chunk the dataset</span>
chunk_size &lt;- <span class="hljs-number">1</span>
n &lt;- nrow(cleaned_recipes_df)
r &lt;- rep(<span class="hljs-number">1</span>:ceiling(n/chunk_size),each = chunk_size)[<span class="hljs-number">1</span>:n]
chunks &lt;- split(cleaned_recipes_df,r)

<span class="hljs-comment">#empty dataframe</span>
recipe_sentence_embeddings &lt;-  data.frame(
  recipe = character(),
  recipe_vec_embeddings = I(list()),
  recipe_id = character()
)

<span class="hljs-comment"># create a progress bar</span>
pb &lt;- txtProgressBar(min = <span class="hljs-number">1</span>, max = length(chunks), style = <span class="hljs-number">3</span>)

<span class="hljs-comment"># embedding data</span>
<span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(chunks)) {
  recipe &lt;- as.character(chunks[i])
  recipe_id &lt;- paste0(<span class="hljs-string">"recipe"</span>,i)
  recipe_embeddings &lt;- textEmbed(as.character(recipe),
                                layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                keep_token_embeddings = <span class="hljs-literal">FALSE</span>,
                                batch_size = <span class="hljs-number">1</span>
  )

  <span class="hljs-comment"># convert tibble to vector</span>
  recipe_vec_embeddings &lt;- unlist(recipe_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
  recipe_vec_embeddings &lt;- list(recipe_vec_embeddings)

  <span class="hljs-comment"># Append the current chunk's data to the dataframe</span>
  recipe_sentence_embeddings &lt;- recipe_sentence_embeddings %&gt;%
    add_row(
      recipe = recipe,
      recipe_vec_embeddings = recipe_vec_embeddings,
      recipe_id = recipe_id
    )

  <span class="hljs-comment"># track embedding progress</span>
  setTxtProgressBar(pb, i)

}

<span class="hljs-comment"># Add documents to the collection</span>
add_documents(
  client,
  <span class="hljs-string">"recipes_collection"</span>,
  documents = recipe_sentence_embeddings$recipe,
  ids = recipe_sentence_embeddings$recipe_id,
  embeddings = recipe_sentence_embeddings$recipe_vec_embeddings
)
</code></pre>
<p><strong>chat.R</strong></p>
<pre><code class="lang-r"><span class="hljs-comment"># Load required packages</span>
<span class="hljs-keyword">library</span>(ellmer)
<span class="hljs-keyword">library</span>(text)
<span class="hljs-keyword">library</span>(rchroma)
<span class="hljs-keyword">library</span>(shinychat)

ui &lt;- bslib::page_fluid(
  chat_ui(<span class="hljs-string">"chat"</span>)
)

server &lt;- <span class="hljs-keyword">function</span>(input, output, session) {
  <span class="hljs-comment"># Connect to a local ChromaDB instance running on docker with embeddings loaded </span>
  client &lt;- chroma_connect()

  <span class="hljs-comment"># sentence embeddings function and query</span>
  question &lt;- <span class="hljs-keyword">function</span>(sentence){
    sentence_embeddings &lt;- textEmbed(sentence,
                                     layers = <span class="hljs-number">10</span>:<span class="hljs-number">11</span>,
                                     aggregation_from_layers_to_tokens = <span class="hljs-string">"concatenate"</span>,
                                     aggregation_from_tokens_to_texts = <span class="hljs-string">"mean"</span>,
                                     keep_token_embeddings = <span class="hljs-literal">FALSE</span>
    )

    <span class="hljs-comment"># convert tibble to vector</span>
    sentence_vec_embeddings &lt;- unlist(sentence_embeddings, use.names = <span class="hljs-literal">FALSE</span>)
    sentence_vec_embeddings &lt;- list(sentence_vec_embeddings)

    <span class="hljs-comment"># Query similar documents</span>
    results &lt;- query(
      client,
      <span class="hljs-string">"recipes_collection"</span>,
      query_embeddings = sentence_vec_embeddings ,
      n_results = <span class="hljs-number">2</span>
    )
    results

  }


  <span class="hljs-comment"># function that provides context</span>
  tool_context  &lt;- tool(
    question,
    <span class="hljs-string">"obtains the right context for a given question"</span>,
    sentence = type_string()

  )

  <span class="hljs-comment">#  Initialize the chat system </span>
  chat &lt;- chat_ollama(system_prompt = <span class="hljs-string">"You are a knowledgeable culinary assistant specializing in recipe recommendations. 
                      You provide tailored meal suggestions based on the user's available ingredients and the desired amount of food or servings.
                      Ensure the recipes align closely with the user's inputs and yield the expected quantity."</span>,
                      model = <span class="hljs-string">"llama3.2:3b-instruct-q4_K_M"</span>)
  <span class="hljs-comment">#register tool</span>
  chat$register_tool(tool_context)

  observeEvent(input$chat_user_input, {
    stream &lt;- chat$stream_async(input$chat_user_input)
    chat_append(<span class="hljs-string">"chat"</span>, stream)
  })
}

shinyApp(ui, server)
</code></pre>
<p>You can find the complete code <a target="_blank" href="https://github.com/elabongaatuo/Recipe-Chatbot/">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building a local Retrieval-Augmented Generation (RAG) application using Ollama and ChromaDB in R programming offers a powerful way to create a specialized conversational assistant.</p>
<p>By leveraging the capabilities of large language models and vector databases, you can efficiently manage and retrieve relevant information from extensive datasets.</p>
<p>This approach not only enhances the performance of language models but also ensures customization and privacy by running the application locally.</p>
<p>Whether you're developing a cooking assistant or any other domain-specific chatbot, this method provides a robust framework for delivering intelligent and contextually aware responses.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744380659737/4e096d1c-87d6-4baa-bbf3-03657e05c182.gif" alt="Chatbot running on Shiny giving relevant recipe after user prompt" class="image--center mx-auto" width="800" height="903" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Weather App with R Shiny ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you’ll learn how to build a weather app in R. Really – a weather app, in R? Wait, hear me out. When you think of R, you probably imagine someone wearing chunky thick prescription glasses and devouring a book. You know, a statisticia... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-weather-app-with-r-shiny/</link>
                <guid isPermaLink="false">67570d22e8032cfb3def7b4e</guid>
                
                    <category>
                        <![CDATA[ rshiny ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Semantic UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elabonga Atuo ]]>
                </dc:creator>
                <pubDate>Mon, 09 Dec 2024 15:30:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733174501446/a177379f-3c32-424a-9fbe-6608310f2ea6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you’ll learn how to build a weather app in R. Really – a weather app, in R? Wait, hear me out.</p>
<p>When you think of R, you probably imagine someone wearing chunky thick prescription glasses and devouring a book. You know, a statistician dealing with complex models, an insane amount of mathematical equations, and copious amounts of data.</p>
<p>But R is far more than just a tool for statistics. It shines when you need to turn raw data into actionable insights and present those insights in a clear, engaging way.</p>
<p>With frameworks like Shiny, R takes this one step further, enabling you to create fully interactive web apps without having to worry about frontends, backends, or learning an entirely new programming language.</p>
<p>In this tutorial, you will create a simple weather app that fetches data from an API and displays the results in a good-looking app.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-project-overview">Project Overview</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-api-keys-storage-and-retrieval">API Keys: Storage and Retrieval</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-your-first-api-call">How to Make Your First API Call</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-the-shiny-app">How to Build the Shiny App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-project-overview">Project Overview</h2>
<p>Here’s what we’re going to be building:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733341336823/dd605385-5531-43c5-924d-dde24b38846b.gif" alt="The R Shiny weather app demo" class="image--center mx-auto" width="1366" height="588" loading="lazy"></p>
<p>For the weather app to work, you will need to make two separate API calls. We’ll use the One Call API 3.0 to update weather data and the OpenWeather API for geocoding. You can get your API Key <a target="_blank" href="https://openweathermap.org/api">here</a>. Just keep in mind that if this is your first time signing up for an API key, activation may take up to 24 hours.</p>
<p>The weather app will take the location/city from user input. The input will then be geocoded by making the call to OpenWeather API. Then, from its response, the coordinates (latitude and longitude) will be extracted. The coordinates will be used as query arguments for the One Call API call to obtain the weather data in JSON format.</p>
<h3 id="heading-prerequisites">Prerequisites:</h3>
<p>To follow along with this tutorial, you will need:</p>
<ul>
<li><p>R programming knowledge</p>
</li>
<li><p>HTML and a bit of JavaScript knowledge</p>
</li>
<li><p>R Studio installed</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733172415724/c4f884f6-b583-4f13-b0f8-eb564ab6531f.png" alt="Weather Update API Flow" class="image--center mx-auto" width="622" height="458" loading="lazy"></p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Create a folder in your desired directory. Set and confirm the project folder as the working directory using the following command in the R console:</p>
<pre><code class="lang-r">setwd(<span class="hljs-string">"path/to/your/project/file"</span>)
getwd()
</code></pre>
<p>Create a project in the set path using the following command:</p>
<pre><code class="lang-r"><span class="hljs-comment">#create R project</span>
usethis::create_project(path = <span class="hljs-string">"."</span>, open = <span class="hljs-literal">FALSE</span>)
</code></pre>
<p>You should have a folder structure that looks like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733166096334/93e004da-4449-4cb4-8ddd-d3082e5687d8.png" alt="project folder structure" class="image--center mx-auto" width="181" height="104" loading="lazy"></p>
<p>Create an R file in the root directory and save it as <code>app.R</code>. All your R code will be contained here.</p>
<p>Install and load the following libraries that you are going to work with:</p>
<pre><code class="lang-r"><span class="hljs-keyword">library</span>(shiny)
<span class="hljs-keyword">library</span>(bslib)
<span class="hljs-keyword">library</span>(shinyjs)
<span class="hljs-keyword">library</span>(httr2)
<span class="hljs-keyword">library</span>(lubridate)
<span class="hljs-keyword">library</span>(shiny.semantic)
</code></pre>
<h2 id="heading-api-keys-storage-and-retrieval">API Keys: Storage and Retrieval</h2>
<p>Storing your credentials in a location separate from your scripts and global environment is a good practice. This ensures security, scalability, and flexibility, especially when working in shared or production environments. The <code>.Renviron</code> file best serves that purpose.</p>
<p>Open and edit your <code>.Renviron</code> file in the following way:</p>
<pre><code class="lang-r"><span class="hljs-comment">#open and edit .Renviron</span>
usethis::edit_r_environ(scope=c(<span class="hljs-string">"project"</span>)
</code></pre>
<p>The scope argument set to <code>project</code> sets up the <code>.Renviron</code> specifically to your project. In the newly opened file, add your API key as follows:</p>
<pre><code class="lang-r">OPENWEATHERAPIKEY=<span class="hljs-string">"yourapikey"</span>
</code></pre>
<h2 id="heading-how-to-make-your-first-api-call">How to Make Your First API Call</h2>
<p>You will be using the httr2 library (built based on httr) to obtain data from the API. It grants you more control over how you make requests to the web.</p>
<h3 id="heading-make-the-api-key-accessible-in-the-script">Make the API Key accessible in the script</h3>
<p>First, you’ll need to securely access and store the API key in the script without hardcoding it. You can do that like this:</p>
<pre><code class="lang-r"><span class="hljs-comment">#access API keys in script</span>
readenviron(<span class="hljs-string">".Renviron"</span>)
api_key = Sys.getenv(<span class="hljs-string">"OPENWEATHERAPIKEY"</span>)
</code></pre>
<h3 id="heading-define-the-geocoding-function">Define the Geocoding Function</h3>
<p>You will create a function that takes a location and an API key as inputs, sends a request to the OpenWeather geocoding API, and returns the coordinates of the specified location.</p>
<p>Start by creating a request. The pipe (<code>|&gt;</code>) operator facilitates the chaining of HTTP requests step by step in a clear and readable manner. The geocoding URL takes two parameters: location, denoted by <code>q</code>, and the API key, denoted by <code>app_id</code>. The <code>req_url_query()</code> function appends these parameters to the query.</p>
<p>Chain the query to perform the request and fetch action, and finally obtain the response in JSON format using the second to last line.</p>
<pre><code class="lang-r"><span class="hljs-comment"># Geocoding URL</span>
geocoding_url &lt;- <span class="hljs-string">"https://api.openweathermap.org/data/2.5/weather"</span>
geocode &lt;- <span class="hljs-keyword">function</span>(location, api_key) {
  request(geocoding_url) |&gt; 
    req_url_query(`q` = location, `appid` = api_key) |&gt; 
    req_perform() |&gt; 
    resp_body_json() |&gt;
    coordinates()
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733342454801/feed01b2-a7a1-4c69-8297-2dcfdc8ec39f.png" alt="A sample response to the geocoding API" class="image--center mx-auto" width="1203" height="284" loading="lazy"></p>
<h3 id="heading-define-the-coordinate-extracting-function">Define the coordinate-extracting function</h3>
<p>The <code>coordinates()</code> function is a helper function that extracts the latitude and longitude values from the JSON response. A quick inspection of the JSON response reveals the coordinate's position. The JSON object is simply a long list of lists and you can access elements by subsetting it.</p>
<p>A blank data body would imply that the city/location is unavailable, and you’d get the message <em>"No such city exists!"</em>. If the JSON contains an element, the length would be more than 0 – it is a list after all.</p>
<pre><code class="lang-r">coordinates &lt;- <span class="hljs-keyword">function</span>(body) {
  <span class="hljs-keyword">if</span>(length(body) != <span class="hljs-number">0</span>) { 
    lat &lt;- body$coord$lat
    lng &lt;- body$coord$lon
    town &lt;- body$name
    c(lat, lng, town)
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-string">"No such city exists!"</span>
  }
}
</code></pre>
<h3 id="heading-define-the-weather-update-function">Define the weather-update function</h3>
<p>You will create a function that sends a request to the OpenWeather API with specified query parameters, handles errors using a predefined function, and returns the parsed JSON response containing the weather data.</p>
<p>As implemented in the geocoding function, start by creating a request and adding the necessary query parameters using the <code>req_url_query()</code> function. The <code>openweather_json()</code> function accepts two main arguments:</p>
<ul>
<li><p><code>api_key</code>: This is a required argument used for authentication with the OpenWeather API matched by position.</p>
</li>
<li><p><code>...</code>: This represents optional keyword arguments that you can use to customize the query. You can pass as many additional parameters as needed, provided they are specified as named arguments.</p>
</li>
</ul>
<pre><code class="lang-r">openweather_json &lt;- <span class="hljs-keyword">function</span>(api_key, <span class="hljs-keyword">...</span>) { 
  request(current_weather_url) |&gt; 
    req_url_query(<span class="hljs-keyword">...</span>, `appid` = api_key, `units` = <span class="hljs-string">"metric"</span>) |&gt; 
    req_error(body = openweather_error_body) |&gt;
    req_perform() |&gt; 
    resp_body_json()
}
</code></pre>
<h3 id="heading-error-handling-extracting-and-managing-status-codes">Error Handling: Extracting and Managing Status Codes</h3>
<p>You will create an error-handling function that extracts non-200 status codes from a response and defines how to manage them. The structure of this function depends on how the API reports errors and where the relevant information is stored.</p>
<h4 id="heading-define-the-weather-update-error-body">Define the weather-update error body</h4>
<p>The <code>req_error()</code> in <code>openweather_json()</code> introduces a new concept: error handling. API requests may throw exceptions, and getting the status codes helps you know what message to show the user and how to resolve it.</p>
<p>Create an error body which is a function that captures the error code if the status code is not 200 (which means everything is OK).</p>
<p>The function takes a response and extracts the status response stored in the JSON response at the <code>$message</code> sublist. The underscore <code>(_)</code>is a placeholder for the JSON object.</p>
<pre><code class="lang-r">openweather_error_body &lt;- <span class="hljs-keyword">function</span>(resp) {
  resp |&gt; resp_body_json() |&gt; _$message 
}
</code></pre>
<h4 id="heading-define-the-geocode-error-body">Define the geocode error body</h4>
<p>This error body function will prove useful in the Shiny App. This is a simple walkthrough.</p>
<p>The <code>req_error()</code> function allows you to customize how response errors are handled. Its <code>is_error</code> argument determines whether a given response should be considered an error. By setting <code>is_error</code> to <code>\(resp) FALSE</code> (an anonymous function that always returns FALSE), all responses, regardless of the status code, are treated as successful. This prevents the app from exiting due to non-200 status codes.</p>
<p>With this setup, you can extract the status code from the response body and pipe it into the <code>resp_status()</code> function to retrieve the exact code.</p>
<pre><code class="lang-r">openstreetmap_error_body &lt;- <span class="hljs-keyword">function</span>(location, api_key) {
  resp &lt;- request(geocoding_url) |&gt; 
    req_url_query(`q` = location, `appid` = api_key) |&gt; 
    req_error(is_error = \(resp) <span class="hljs-literal">FALSE</span>) |&gt;
    req_perform() |&gt;  resp_status()
  resp
}
</code></pre>
<h2 id="heading-how-to-build-the-shiny-app">How to Build the Shiny App</h2>
<p>Now that you have nailed down how to obtain data from the API, it’s time to render the results in an interpretable and interactive format. For this, you will use Shiny. Shiny is a framework that allows you to create interactive web apps.</p>
<p>A Shiny App is made up of two components:</p>
<ul>
<li><p>The UI: what the user interacts with. It defines the layout and appearance of the app.</p>
</li>
<li><p>The server: contains the app’s logic and behaviour.</p>
</li>
</ul>
<h3 id="heading-building-the-shiny-ui">Building the Shiny UI</h3>
<p>Shiny UI provides a collection of elements that allow users to input data, make selections, and trigger events seamlessly.</p>
<p>You will include a <code>textInput</code> element that takes in the location and the weather data will be fetched and rendered upon submission. The <code>input_task_button</code> button prevents the user from clicking when an API call is in progress. The other elements are output elements where the weather data will be displayed and a mode-switching button.</p>
<h4 id="heading-styling-the-shiny-app">Styling the Shiny app</h4>
<p>You can use <code>shiny.semantic</code>, a library built on top of Fomantic-UI, to style your Shiny dashboard. Fomantic-UI is a front-end framework that provides a rich collection of pre-styled HTML components like buttons, modals, form inputs, and more. It simplifies UI design by allowing developers to create visually appealing and responsive interfaces without needing extensive custom CSS or HTML knowledge.</p>
<p>Fomantic-UI styling is applied by wrapping elements in their corresponding classes, which define their behavior and appearance.</p>
<p>A grid in Fomantic-UI is a flexible layout system used to organize content. It acts as a canvas that divides the layout into rows (horizontally aligned) and columns (vertically aligned). A root grid can contain up to 16 columns, making it ideal for creating structured and responsive designs.</p>
<p>To specify a column's width, you append classes like wide and the size (a number from 1 to 16) to represent its span. The total width of all columns in a row should sum up to 16.</p>
<p>A segment groups related content, while a card displays detailed, content-rich items, such as a user's social media profile. Dividers are visual elements used to separate sections or content within a layout.</p>
<p>For the weather app, first create a div of class <code>grid</code> within which you’ll nest the various elements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733137762676/12d5695c-2ed7-4606-8267-44243c2bee57.png" alt="semantic page layout demo" class="image--center mx-auto" width="885" height="568" loading="lazy"></p>
<h5 id="heading-search-bar-section"><strong>Search bar section</strong></h5>
<p>Divide the grid into sixteen columns and create a segment that groups elements in the search bar section. Add a theme toggle button, location input that takes in user input, a search button for submitting the location to the API, and a notification button, defining their width by the column size.</p>
<pre><code class="lang-r">div(class = <span class="hljs-string">"sixteen wide column"</span>,
          div(class = <span class="hljs-string">"ui segment"</span>,
              div(class = <span class="hljs-string">"ui grid"</span>,
                  div(class = <span class="hljs-string">"two wide column"</span>,
                      button(
                        class = <span class="hljs-string">"ui button icon basic"</span>,
                        input_id = <span class="hljs-string">"darkmode"</span>,
                        label = <span class="hljs-literal">NULL</span>,
                        icon = icon(<span class="hljs-string">"moon icon"</span>)
                      )
                  ),
                  div(class = <span class="hljs-string">"ten wide column"</span>,
                      textInput(
                        <span class="hljs-string">"location"</span>,
                        label = <span class="hljs-literal">NULL</span>,
                        placeholder = <span class="hljs-string">"Search for your preferred city"</span>
                      )
                  ),
                  div(class = <span class="hljs-string">"two wide column"</span>,
                      tags$div(
                        class = <span class="hljs-string">"ui button"</span>,
                        id = <span class="hljs-string">"my-custom-button"</span>,
                        input_task_button(<span class="hljs-string">"search"</span>, label = <span class="hljs-string">"Search"</span>, icon = icon(<span class="hljs-string">"search"</span>))
                      )
                  ),
                  div(class = <span class="hljs-string">"two wide column"</span>,
                      actionButton(<span class="hljs-string">"show_alert"</span>, label = icon(<span class="hljs-string">"bell"</span>), class = <span class="hljs-string">"bell-no-alert"</span>),
                      textOutput(<span class="hljs-string">"alert_message"</span>)
                  )
              )
          )
      )
</code></pre>
<h5 id="heading-location-and-current-weather-section"><strong>Location and current weather section</strong></h5>
<p>Divide the grid into sixteen columns and nest another grid within the partitions that will host two columns.</p>
<p>Within the grid, define two columns. The first column is for time, location, and date data, and the second column will hold current weather data.</p>
<p>Then create card elements to hold each weather parameter, its unit of measurement, and the corresponding icon.</p>
<pre><code class="lang-r">div(class = <span class="hljs-string">"sixteen wide column"</span>,
          div(class = <span class="hljs-string">"ui equal-height-grid grid"</span>,
              div(class = <span class="hljs-string">"left floated center aligned four wide column"</span>,
                  div(class = <span class="hljs-string">"ui raised equal-height-two-segment segment"</span>,
                      style = <span class="hljs-string">"flex: 1;"</span>,
                      div(class = <span class="hljs-string">"column center aligned"</span>,
                          div(class = <span class="hljs-string">"ui hidden section divider"</span>),
                          span(class = <span class="hljs-string">"ui large text"</span>, textOutput(<span class="hljs-string">"city"</span>)),
                          div(class = <span class="hljs-string">"ui hidden section divider"</span>),
                          span(class = <span class="hljs-string">"ui big text"</span>, textOutput(<span class="hljs-string">"currentTime"</span>)),
                          div(class = <span class="hljs-string">"ui hidden section divider"</span>),
                          span(class = <span class="hljs-string">"ui large text"</span>, textOutput(<span class="hljs-string">"currentDate"</span>)),
                          div(class = <span class="hljs-string">"ui hidden section divider"</span>)
                      )
                  )
              ),
              div(class = <span class="hljs-string">"right floated center aligned twelve wide column"</span>,
                  div(class = <span class="hljs-string">"ui raised segment"</span>,
                      div(class = <span class="hljs-string">"ui horizontal equal width segments"</span>,
                          div(class = <span class="hljs-string">"ui equal-height-two-segment segment"</span>,
                              style = <span class="hljs-string">"flex: 3;"</span>,
                              div(class = <span class="hljs-string">"column"</span>,
                                  span(class = <span class="hljs-string">"ui big text centered"</span>, textOutput(<span class="hljs-string">"currentTemp"</span>)),
                                  textOutput(<span class="hljs-string">"feelsLike"</span>),
                                  card(
                                    class = <span class="hljs-string">"ui mini"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"large sun"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"Sunrise"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"sunriseTime"</span>))
                                    )
                                  ),
                                  card(
                                    class = <span class="hljs-string">"ui mini"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"large moon"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"Sunset"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"sunsetTime"</span>))
                                    )
                                  )
                              )
                          ),
                          div(class = <span class="hljs-string">"ui segment"</span>,
                              style = <span class="hljs-string">"flex: 3;"</span>,
                              div(
                                class = <span class="hljs-string">"column center aligned"</span>,
                                div(class = <span class="hljs-string">"ui hidden divider"</span>),
                                htmlOutput(<span class="hljs-string">"currentWeatherIcon"</span>),
                                span(class = <span class="hljs-string">"ui large text"</span>, textOutput(<span class="hljs-string">"currentWeatherDescription"</span>))
                              )
                          ),
                          div(class = <span class="hljs-string">"ui segment"</span>,
                              style = <span class="hljs-string">"flex: 3;"</span>,
                              div(class = <span class="hljs-string">"column"</span>,
                                  card(
                                    class = <span class="hljs-string">"ui tiny"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"big tint"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"Humidity"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"currentHumidity"</span>))
                                    )
                                  ),
                                  card(
                                    class = <span class="hljs-string">"ui tiny"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"big tachometer alternate"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"Pressure"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"currentPressure"</span>))
                                    )
                                  )
                              )
                          ),
                          div(class = <span class="hljs-string">"ui segment"</span>,
                              style = <span class="hljs-string">"flex: 3;"</span>,
                              div(class = <span class="hljs-string">"column center aligned"</span>,
                                  card(
                                    class = <span class="hljs-string">"ui tiny"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"big wind"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"Wind Speed"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"currentWindSpeed"</span>))
                                    )
                                  ),
                                  card(
                                    class = <span class="hljs-string">"ui tiny"</span>,
                                    div(class = <span class="hljs-string">"content"</span>, icon(class = <span class="hljs-string">"big umbrella"</span>),
                                        div(class = <span class="hljs-string">"sub header"</span>, <span class="hljs-string">"UV Index"</span>),
                                        div(class = <span class="hljs-string">"description"</span>, textOutput(<span class="hljs-string">"currentUV"</span>))
                                    )
                                  )
                              )
                          )
                      )
                  )
              )
          )
      )
</code></pre>
<p><strong>Forecast section</strong></p>
<p>This section holds the forecasted data. Divide the grid into sixteen columns and nest another grid within the partitions hosting two columns.</p>
<p>Within the grid, define two columns. The first column holds the <em>5-Day Forecast</em> data. Separate the elements containing different values using rows. The second column contains <em>Hourly Forecast</em> data. Separate the elements containing different values using columns.</p>
<pre><code class="lang-r">      <span class="hljs-comment"># Forecast section</span>
      div(class = <span class="hljs-string">"sixteen wide column"</span>,
          div(class = <span class="hljs-string">"ui grid equal-height-grid"</span>,
              div(class = <span class="hljs-string">"left floated center aligned six wide column"</span>,
                  div(class = <span class="hljs-string">"ui raised segment special-segment equal-height-segment"</span>,
                      h4(<span class="hljs-string">"5 Days Forecast:"</span>),
                      div(class = <span class="hljs-string">"ui three column special-column grid"</span>,
                          <span class="hljs-comment"># Day forecasts</span>
                          div(class = <span class="hljs-string">"row"</span>,
                              div(class = <span class="hljs-string">"five wide column"</span>, textOutput(<span class="hljs-string">"dailyDtOne"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, textOutput(<span class="hljs-string">"dailyTempOne"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, htmlOutput(<span class="hljs-string">"dailyIconOne"</span>))
                          ),
                          div(class = <span class="hljs-string">"row"</span>,
                              div(class = <span class="hljs-string">"five wide column"</span>, textOutput(<span class="hljs-string">"dailyDtTwo"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, textOutput(<span class="hljs-string">"dailyTempTwo"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, htmlOutput(<span class="hljs-string">"dailyIconTwo"</span>))
                          ),
                          div(class = <span class="hljs-string">"row"</span>,
                              div(class = <span class="hljs-string">"five wide column"</span>, textOutput(<span class="hljs-string">"dailyDtThree"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, textOutput(<span class="hljs-string">"dailyTempThree"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, htmlOutput(<span class="hljs-string">"dailyIconThree"</span>))
                          ),
                          div(class = <span class="hljs-string">"row"</span>,
                              div(class = <span class="hljs-string">"five wide column"</span>, textOutput(<span class="hljs-string">"dailyDtFour"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, textOutput(<span class="hljs-string">"dailyTempFour"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, htmlOutput(<span class="hljs-string">"dailyIconFour"</span>))
                          ),
                          div(class = <span class="hljs-string">"row"</span>,
                              div(class = <span class="hljs-string">"five wide column"</span>, textOutput(<span class="hljs-string">"dailyDtFive"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, textOutput(<span class="hljs-string">"dailyTempFive"</span>)),
                              div(class = <span class="hljs-string">"three wide column"</span>, htmlOutput(<span class="hljs-string">"dailyIconFive"</span>))
                          )
                      )
                  )
              ),
              div(class = <span class="hljs-string">"right floated center aligned ten wide column"</span>,
                  div(class = <span class="hljs-string">"ui raised segment special-segment equal-height-segment"</span>,
                      h4(<span class="hljs-string">"Hourly Forecast:"</span>),
                      div(
                        class = <span class="hljs-string">"ui grid"</span>,
                        style = <span class="hljs-string">"display: flex; flex-direction: row; align-items: center; justify-content: space-around; flex-wrap: wrap; height: 100%;"</span>,
                        <span class="hljs-comment"># Hourly forecasts</span>
                        div(class = <span class="hljs-string">"column"</span>,
                            textOutput(<span class="hljs-string">"hourlyDtOne"</span>),
                            htmlOutput(<span class="hljs-string">"hourlyIconOne"</span>),
                            textOutput(<span class="hljs-string">"hourlyTempOne"</span>)
                        ),
                        div(class = <span class="hljs-string">"column"</span>,
                            textOutput(<span class="hljs-string">"hourlyDtTwo"</span>),
                            htmlOutput(<span class="hljs-string">"hourlyIconTwo"</span>),
                            textOutput(<span class="hljs-string">"hourlyTempTwo"</span>)
                        ),
                        div(class = <span class="hljs-string">"column"</span>,
                            textOutput(<span class="hljs-string">"hourlyDtThree"</span>),
                            htmlOutput(<span class="hljs-string">"hourlyIconThree"</span>),
                            textOutput(<span class="hljs-string">"hourlyTempThree"</span>)
                        ),
                        div(class = <span class="hljs-string">"column"</span>,
                            textOutput(<span class="hljs-string">"hourlyDtFour"</span>),
                            htmlOutput(<span class="hljs-string">"hourlyIconFour"</span>),
                            textOutput(<span class="hljs-string">"hourlyTempFour"</span>)
                        ),
                        div(class = <span class="hljs-string">"column"</span>,
                            textOutput(<span class="hljs-string">"hourlyDtFive"</span>),
                            htmlOutput(<span class="hljs-string">"hourlyIconFive"</span>),
                            textOutput(<span class="hljs-string">"hourlyTempFive"</span>)
                        )
                      )
                  )
              )
          )
      )
  )
</code></pre>
<h3 id="heading-building-the-shiny-server">Building the Shiny Server</h3>
<p>Each element in the UI section has an ID (unique identifier) that is used to manipulate what data/information will be displayed to it.</p>
<p>The <code>render*()</code> set of functions defines the visualization type while the <code>output$*</code> functions subset elements. These two are used to link the visual to the logic. Most elements will have data extracted from the JSON list, except for the weather icons (for which an external link as a source will be referenced).</p>
<h4 id="heading-reactivity">Reactivity</h4>
<p>Reactivity is what makes Shiny apps dynamic—outputs automatically update when their dependencies change.</p>
<p>Two key components of reactivity are reactives and observers. A reactive computes and returns a value based on its dependencies, while an observer monitors reactive values and runs code that causes side effects, like logging or updating a database.</p>
<p>To control reactivity, you can use <code>bindEvent()</code> to delay execution until a specific event occurs or <code>observeEvent()</code> to listen for a user action and trigger a code block. Together, these tools provide flexibility for managing app behavior.</p>
<h4 id="heading-the-server-code">The Server Code</h4>
<ol>
<li><code>location</code> <strong>reactive</strong></li>
</ol>
<p>The location reactive includes an if-else conditional block that defines what message to display depending on the status code. The query variable contains the city/location that will be geocoded to obtain coordinates. The flow is piped to <code>bindEvent()</code>. This ensures the geocoding API call is completed before another call can be made, which reduces unnecessary requests.</p>
<pre><code class="lang-r">location &lt;- reactive({
    query &lt;- input$location
    <span class="hljs-keyword">if</span>(openstreetmap_error_body(query, api_key) == <span class="hljs-string">"404"</span>){
      validate(<span class="hljs-string">"No such city/town exists. Check your spelling!"</span>)
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(openstreetmap_error_body(query, api_key) == <span class="hljs-string">"400"</span>){
      validate(<span class="hljs-string">"Bad request"</span>)
    }
    coords &lt;- geocode(query, api_key)
  }) %&gt;% bindEvent(input$search)
</code></pre>
<ol start="2">
<li><code>weather_data</code> <strong>reactive</strong></li>
</ol>
<p>The weather reactive combines a geocoding API call and a weather update API call using coordinates obtained and extracted from <code>location()</code>:</p>
<pre><code class="lang-r">  weather_data &lt;- reactive({
    loc &lt;- location()
    openweather_json(api_key, lat = loc[<span class="hljs-number">1</span>], lon = loc[<span class="hljs-number">2</span>])
  })
</code></pre>
<p>To access the JSON objects returned by the API call, you call the reactive as if it were a function. The specific values to be extracted can then be accessed by subsetting the JSON value.</p>
<pre><code class="lang-r"><span class="hljs-comment"># subsetting weather data.</span>
  output$city &lt;- renderText({
    location()[<span class="hljs-number">3</span>]
  })

  output$currentWeatherDescription &lt;- renderText({
    weather_data()$current$weather[[<span class="hljs-number">1</span>]]$description
  })
</code></pre>
<ol start="3">
<li><strong>Create a Parse Date function</strong></li>
</ol>
<p>All the time data in the JSON response, forecasted or current, is provided in UNIX format. To make this information user-friendly, it needs to be converted into a human-readable format. You can do this by creating a function that takes the time data as input and uses functions from the <code>lubridate</code> package to handle the conversion.</p>
<p>First, convert the timestamp element to a datetime object. Format the time item to a 12-hour clock system and a date item to include the day of the week, the date, and the month.</p>
<ul>
<li><p><code>%I</code>: Displays the hour in a 12-hour clock format (01-12).</p>
</li>
<li><p><code>%M</code>: Displays the minutes (00-59).</p>
</li>
<li><p><code>%p</code>: Adds the AM/PM indicator.</p>
</li>
</ul>
<p>The paste function concatenates the values. The function returns a vector containing date and time values to be extracted by subsetting.</p>
<pre><code class="lang-r">parse_date &lt;- <span class="hljs-keyword">function</span>(timestamp) {
  datetime &lt;- as_datetime(timestamp) 
  date &lt;- paste(weekdays(datetime), <span class="hljs-string">","</span>, day(datetime), months(datetime))
  time &lt;- format(as.POSIXct(datetime), format = <span class="hljs-string">"%I:%M %p"</span>)
  c(date, time)
}
</code></pre>
<ol start="4">
<li><strong>Add a modal to display error messages</strong></li>
</ol>
<p>The <code>location</code> reactive provides a way to handle errors. You can incorporate a modal to enhance the user experience by overlaying the page and disabling its content until the user completes a specified action whenever an error occurs.</p>
<p>You’ll add JavaScript to control when and how the modal shows.</p>
<p>Add two modals in the UI section, each featuring an explanation of the error (header) and an outline of the required action (content). The <code>action</code> class includes a button that enables the user to close the modal.</p>
<pre><code class="lang-r"><span class="hljs-comment"># modals - UI</span>
  div(id = <span class="hljs-string">"notFound"</span>, class = <span class="hljs-string">"ui modal"</span>,
      div(class = <span class="hljs-string">"header"</span>, <span class="hljs-string">"Location Not Found"</span>),
      div(class = <span class="hljs-string">"content"</span>, <span class="hljs-string">"No such city/town exists. Check your spelling!"</span>),
      div(class = <span class="hljs-string">"actions"</span>,
          div(class = <span class="hljs-string">"ui button"</span>, id = <span class="hljs-string">"closeNotFound"</span>, <span class="hljs-string">"OK"</span>))
  ),
  div(id = <span class="hljs-string">"badRequest"</span>, class = <span class="hljs-string">"ui modal"</span>,
      div(class = <span class="hljs-string">"header"</span>, <span class="hljs-string">"Invalid Request"</span>),
      div(class = <span class="hljs-string">"content"</span>, <span class="hljs-string">"Bad request. Please try again with valid details."</span>),
      div(class = <span class="hljs-string">"actions"</span>,
          div(class = <span class="hljs-string">"ui button"</span>, id = <span class="hljs-string">"closeBadRequest"</span>, <span class="hljs-string">"OK"</span>))
  )
</code></pre>
<p>Slightly adjust the location reactive to incorporate the modal. The commented-out code will be replaced with the JavaScript lines. The <code>runjs</code> function shows the modal depending on the error encountered. <code>req(FALSE)</code> terminates the reactive flow.</p>
<pre><code class="lang-r"><span class="hljs-comment"># show and hide modals  - Server</span>
location &lt;- reactive({
    query &lt;- input$location
    <span class="hljs-keyword">if</span>(openstreetmap_error_body(query, api_key) == <span class="hljs-string">"404"</span>){
      <span class="hljs-comment">#validate("No such city/town exists. Check your spelling!")</span>
      runjs(<span class="hljs-string">"$('#notFound').modal('show');"</span>)
      req(<span class="hljs-literal">FALSE</span>)
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(openstreetmap_error_body(query, api_key) == <span class="hljs-string">"400"</span>){
      <span class="hljs-comment">#validate("Bad request")</span>
      runjs(<span class="hljs-string">"$('#badRequest').modal('show');"</span>)
      req(<span class="hljs-literal">FALSE</span>)
    }
    coords &lt;- geocode(query, api_key)
  }) %&gt;% bindEvent(input$search)

<span class="hljs-comment"># listens for button click on modals to hide modal</span>
observeEvent(input$closeNotFound, {
    runjs(<span class="hljs-string">"$('#notFound').modal('hide');"</span>)
  })

observeEvent(input$closeBadRequest, {
    runjs(<span class="hljs-string">"$('#badRequest').modal('hide');"</span>)
  })
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have built a weather app using Shiny that retrieves weather data from an API and displays it in an interactive and visually appealing way.</p>
<p>To do this, you used the following libraries:</p>
<ul>
<li><p><code>httr2</code> for making API requests and handling responses</p>
</li>
<li><p><code>shiny.semantic</code> for styling the app</p>
</li>
<li><p><code>lubridate</code> for working with and formatting time data</p>
</li>
<li><p><code>shinyjs</code> for integrating JavaScript features into the app</p>
</li>
</ul>
<p>This combination of tools allowed you to create a functional, user-friendly weather app.</p>
<p>You can find the complete code for the project <a target="_blank" href="https://github.com/elabongaatuo/R-weather-app">here</a>.</p>
<p>La Fin!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Run R Programs Directly in Jupyter Notebook Locally ]]>
                </title>
                <description>
                    <![CDATA[ R is a popular programming language that’s now widely used in research-related fields like Bioinformatics. And to use R, you’ll need to install the R Compiler and R Studio. But did you know that you can also directly run your R code right in a Jupyte... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-run-r-programs-directly-in-jupyter-notebook-locally/</link>
                <guid isPermaLink="false">66feeca1dbd895463237bf4b</guid>
                
                    <category>
                        <![CDATA[ R ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jupyter Notebook  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jupyterhub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jupyter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Miniconda ]]>
                    </category>
                
                    <category>
                        <![CDATA[ anaconda ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Md. Fahim Bin Amin ]]>
                </dc:creator>
                <pubDate>Thu, 03 Oct 2024 19:12:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/pUAM5hPaCRI/upload/d8014cab22d10f9bade9077d0d4af34b.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>R is a popular programming language that’s now widely used in research-related fields like Bioinformatics.</p>
<p>And to use R, you’ll need to install the R Compiler and R Studio. But did you know that you can also directly run your R code right in a Jupyter Notebook? This helps in so many ways if you are already used to using Jupyter Notebook for Machine Learning-related tasks using Python.</p>
<p>In this tutorial, I’ll show you exactly how you can set up your local machine to run the R programming language directly in Jupyter Notebook. The processes I am going to show you today are equally applicable to all major operating systems (Windows, MacOS, and Linux OSes).</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-install-conda">Install Conda</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-a-new-environment">Create a New Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-activate-your-conda-environment">Activate Your Conda Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-install-ipykernel-and-jupyter">Install ipykernel and jupyter</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-install-r-in-the-conda-environment">Install R in the Conda Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-open-the-jupyter-notebook">Open the Jupyter Notebook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-r-in-jupyter-notebook">Run R in Jupyter Notebook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-install-conda">Install Conda</h2>
<p>You’d normally use Conda to handle multiple environments in Python. And here, we’re going to use the same Conda program to install R in our environment. You can either use <a target="_blank" href="https://www.anaconda.com/">Anaconda</a> or <a target="_blank" href="https://docs.anaconda.com/miniconda/">Miniconda</a>.</p>
<p>I prefer Miniconda as it’s so lightweight. You’ll also get the opportunity to install the latest packages directly using Miniconda. But you can simply go with the Anaconda if you are already comfortable with that.</p>
<h2 id="heading-create-a-new-environment">Create a New Environment</h2>
<p>Many people tend to use the Base environment. But I never like to use the Base environment directly as you typically need multiple environments for handling different package and versions of packages as well.</p>
<p>So I’ll create a new environment where I’ll work on my R programming language-related tasks using Jupyter Notebook.</p>
<p>To create a new Conda environment, simply use the following command:</p>
<pre><code class="lang-bash">conda create --name r-conda
</code></pre>
<p>Here, <code>r-conda</code> is my Conda environment’s name. You can choose any other name, but keep in mind that the conda env name can not have any whitespaces in it.</p>
<p>It will create a new Conda environment named <code>r-conda</code> for me.</p>
<h2 id="heading-activate-your-conda-environment">Activate Your Conda Environment</h2>
<p>If you want to work on a separate conda environment, you’ll need to make sure that you’re activating that specific conda environment before starting to do anything.</p>
<p>I want to work on the <code>r-conda</code> conda environment. So I can simply activate the conda environment using the following command:</p>
<pre><code class="lang-bash">conda activate r-conda
</code></pre>
<p>You need to use the exact conda env name that you want if it’s different than <code>r-conda</code> in the command.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Keep in mind that you need to activate the conda environment successfully before proceeding further.</div>
</div>

<p>You will see the conda environment’s name as <code>(conda-env-name)</code> at the left side of your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727898007890/f8bf9ced-6c9e-4198-9116-63a32e7d0f03.png" alt="activate conda env" class="image--center mx-auto" width="1097" height="553" loading="lazy"></p>
<h2 id="heading-install-ipykernel-and-jupyter">Install <code>ipykernel</code> and <code>jupyter</code></h2>
<p>I always like to install the <code>ipykernel</code> and <code>jupyter</code> in all of my conda environments as they help manage different conda environments’ Jupyter notebooks/labs separately.</p>
<p>So I’m going to install them together in my conda env by using the command below:</p>
<pre><code class="lang-bash">conda install ipykernel jupyter
</code></pre>
<p>This will install both <code>ipykernel</code> and <code>jupyter</code> in the activated conda environment.</p>
<h2 id="heading-install-r-in-the-conda-environment">Install R in the Conda Environment</h2>
<p>To install R directly in the conda environment, simply use the following command:</p>
<pre><code class="lang-bash">conda install -c r r-irkernel
</code></pre>
<p>This will install the necessary components that enable your local computer to run the R program in your Jupyter Notebook.</p>
<h2 id="heading-open-the-jupyter-notebook">Open the Jupyter Notebook</h2>
<p>Now you can open the Jupyter Notebook either by using <code>jupyter notebook</code> or <code>jupyter notebook --ip=0.0.0.0 --port=8889 --no-browser --allow-root --NotebookApp.token=''</code>. Just make sure to modify the IP, port, root configuration, and token as you see fit for your work.</p>
<p>Open the given link in the terminal to open Jupyter Notebook in your web browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727898291254/b932284e-05af-4eec-a6aa-f6b9ad50dd1c.png" alt="Open Jupyter Notebook" class="image--center mx-auto" width="1094" height="541" loading="lazy"></p>
<h2 id="heading-run-r-in-jupyter-notebook">Run R in Jupyter Notebook</h2>
<p>After opening Jupyter Notebook in your web browser, when you want to create a new notebook for R, you will get <code>R</code> directly in the “New” menu like the image given below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727898368089/a2d22b41-8ddd-480b-aaa4-65aeafb12f69.png" alt="R in notebook" class="image--center mx-auto" width="357" height="268" loading="lazy"></p>
<p>Now, you can use the R language directly in your Jupyter Notebook!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727898457072/05015331-742c-49c5-9325-b1d1cb1fc6cd.png" alt="Run &quot;R&quot; in Jupyter Notebook" class="image--center mx-auto" width="1244" height="524" loading="lazy"></p>
<p>You can also see the R programming language logo at the top right side of your Notebook.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Thank you for reading the entire article. I hope you have learned something new here.</p>
<p>If you have enjoyed the procedures step-by-step, then don't forget to let me know on <a target="_blank" href="https://twitter.com/Fahim_FBA">Twitter/X</a> or <a target="_blank" href="https://www.linkedin.com/in/fahimfba/">LinkedIn</a>. I would appreciate it if you could endorse me for some relevant skillsets on <a target="_blank" href="https://www.linkedin.com/in/fahimfba/">LinkedIn</a>. I would also recommend that you subscribe to my <a target="_blank" href="https://youtube.com/@FahimAmin">YouTube channel</a> for regular programming-related content.</p>
<p>You can follow me on <a target="_blank" href="https://github.com/FahimFBA">GitHub</a> as well if you are interested in open source. Make sure to check <a target="_blank" href="https://fahimbinamin.com/">my website</a> as well.</p>
<p>Thank you so much! 😀</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build Interactive Data-Driven Web Apps With R Shiny ]]>
                </title>
                <description>
                    <![CDATA[ Shiny is an R package that makes it easy to build interactive and data-driven web apps straight from R. We just published a course on the freeCodeCamp.org YouTube channel that will teach you how to use R Shiny. Dr. Chanin Nantasenamat, also known as ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-interactive-data-driven-web-apps-with-r-shiny/</link>
                <guid isPermaLink="false">66b20107a8b92c932923640d</guid>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 22 Sep 2021 13:17:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/maxresdefault-1.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Shiny is an R package that makes it easy to build interactive and data-driven web apps straight from R.</p>
<p>We just published a course on the freeCodeCamp.org YouTube channel that will teach you how to use R Shiny.</p>
<p>Dr. Chanin Nantasenamat, also known as the Data Professor, teaches this course. He is an Associate Professor of Bioinformatics at a Research University and has more than 15 years of experience in data science.</p>
<p>Apps created with Shiny can be hosted on a standalone webpage or embedded in R Markdown documents. Shiny makes it possible to build these web apps from R and also to create them using only R code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/giphy--2-.gif" alt="Image" width="600" height="400" loading="lazy">
<em>This R is a little shiny. :)</em></p>
<p>In this course you will first will learn the basics of Shiny. Then you will learn how to use Shiny to build the following apps:</p>
<ul>
<li>Print User Input</li>
<li>Display Histogram</li>
<li>Machine Learning (Weather Dataset)</li>
<li>Machine Learning (Iris Dataset)</li>
<li>BMI Calculator</li>
</ul>
<p>After building those apps, you will learn how to deploy them using Heroku.</p>
<p>Watch the full course below or <a target="_blank" href="https://youtu.be/9uFQECk30kA">on the freeCodeCamp.org YouTube channel</a> (90-minute watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9uFQECk30kA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-transcript">Transcript</h2>
<p>(autogenerated)</p>
<p>Learn to use R to build an interactive data driven application with the R shiny package.</p>
<p>Dr. Chanin Nantasenamat, also known as the Data Professor, teaches this course.</p>
<p>Besides teaching on his YouTube channel, he is also a university professor.</p>
<p>You probably know that the our programming language can help you to perform statistical analysis.</p>
<p>But did you know that you could use our to build an interactive data driven web application.</p>
<p>In this course on Free Code Camp, you will be learning about how you could use the our shiny package to build an interactive and data driven web application that will range from a simple application that allows you to print user inputs, web applications that will allow you to display data visualization, as well as web application that will allow you to make predictions from machine learning models.</p>
<p>Finally, you'll be learning how to deploy the web applications that you have created to the cloud by means of the Heroku platform.</p>
<p>All codes that are used in this tutorial will be provided in the video description.</p>
<p>And without further ado, let's dive in.</p>
<p>Before we begin, let's cover the basics of what is a shiny package.</p>
<p>so shiny is an art package that allows you to build an interactive web application, there are several extension packages that will allow you to extend the function of shiny, including shiny themes, shiny dashboard, shiny j, s and several others.</p>
<p>And once you develop your web app in shiny, then you want to deploy it.</p>
<p>So you have two options, you want to deploy it on your own server, for example, using a service like Digital Ocean or to a shiny apps.io.</p>
<p>There are lots of example codes that can get you started.</p>
<p>And this is available in the shiny gallery.</p>
<p>So the links are in the slides.</p>
<p>Okay, so what we will learn today, first of all, we will learn about the structure of a shiny web application.</p>
<p>And then we're going to have a look at some of the examples of the shiny web application.</p>
<p>And finally, we will show you step by step how you can build your interactive web application.</p>
<p>So let's have a look at the structure of a shiny web application.</p>
<p>So essentially, a shiny web app comprises of three components.</p>
<p>So the first component is the user interface, which is housed within a file called UI dot r.</p>
<p>And the second is the server function, which will perform the processing of the data, which is housed in the file called server dot r.</p>
<p>And then the shiny app function will fuse the UI and server components together.</p>
<p>So the UI is the front end that accepts the user input values, the server is the back end that processes these input values to finally produce output results that are displayed on the website.</p>
<p>Okay, so you see that input data will flow into the user interface, which is the website that you see.</p>
<p>And then you will enter data into the text box, and then the data will be submitted to the server, the server processes the information, and then it will produce the result.</p>
<p>And the result is displayed on the websites.</p>
<p>Okay, and then the user will see the results.</p>
<p>Okay, so let's have a look at some of the shiny web applications.</p>
<p>So let's go to this link.</p>
<p>Okay, so this is the gallery available from SHINee.</p>
<p>And you can see that there are a lot of examples.</p>
<p>So there are the integration of maps, right insights, shiny application, and also interactive scatter plots.</p>
<p>You can also embed Google charts as well, you could perform k means clustering, you could create some bar charts using available data set from the data set package.</p>
<p>And then you could also create a word cloud, okay, and there are several others.</p>
<p>And then there are witches like buttons, tables, slider, input, slider, K, downloading files, uploading files, subsetting, data set and all that.</p>
<p>Okay, so there are several examples on how you can develop custom shiny web apps.</p>
<p>So why don't we click on one, the first one, okay, so this map is interactive.</p>
<p>If we click on it, we can zoom in.</p>
<p>Right, so you click on the color, and then it will update the map based on your input are also Data Explorer.</p>
<p>So it's an interactive table.</p>
<p>You can also sort the data as well, okay.</p>
<p>Or how about a word cloud generator.</p>
<p>Can you could play around with the input parameters, minimum frequency of each word.</p>
<p>For example, if it's 25, it means that the current word like love has to Be present at least 25 times.</p>
<p>So 26 times in order for it to be counted here, how many words are we limiting to be displayed here? Okay, and these accept input from the books of our choice A Midsummer's night dream, The Merchant of Venice or Romeo and Juliet, we have to click on the Change button.</p>
<p>k.</p>
<p>k means clustering, using the iris dataset, right.</p>
<p>Okay.</p>
<p>Okay, and then the next one is to have a look at some of the web applications coming out of my own research lab.</p>
<p>So let's have a look.</p>
<p>Let's go to code stop bio slash osfp.</p>
<p>So as I'm a bioinformatics researcher, and data scientist, so what we do in our lab is we try to apply machine learning in order to make sense of biological data and chemical data as well.</p>
<p>And so the objective of this web server is to take as input the protein sequence, and then we will predict whether the protein sequence is an oligomer or a monomer.</p>
<p>Okay, so let's click on the Insert example data, and then the input will be a fast a format of the protein sequence.</p>
<p>So the first line which contains the greater than symbol, followed by the name of the protein is given here.</p>
<p>So we see that the first protein is a monomer.</p>
<p>And the second protein is a tetra mer.</p>
<p>And let's click on the submit button to make the prediction.</p>
<p>Okay, and so we see that the prediction is correct on both occasion, because the first one is a monomer.</p>
<p>And it predicts it to be a monomer.</p>
<p>And the second one is a tetramer.</p>
<p>And it predicts it to be an ollie Gomer.</p>
<p>Okay, so this is the interface of the prediction web server.</p>
<p>And if we click on the other buttons, it will look like any other ordinary website.</p>
<p>Okay, so these are description on how to use the web server.</p>
<p>And they are written in markdown case.</p>
<p>So this shiny app can also embed markdown inside as well.</p>
<p>Okay, so we also provide the data set for download as well.</p>
<p>And we host it on the GitHub.</p>
<p>And if you're interested in reading this paper, you can click on the link.</p>
<p>Okay, so this is the paper that we published back in 2016, in the Journal of Chem informatics.</p>
<p>Okay, so let's go back to the slide.</p>
<p>And let's get started.</p>
<p>We're creating our own web app using SHINee.</p>
<p>So what you want to do now is fire up your our studio or our studio cloud K.</p>
<p>And so the code that will be used today is available on the data Professor GitHub.</p>
<p>So if you go to github.com, slash data professor, okay, and then you click on code, and then find SHINee slash 001 first app.</p>
<p>And then you want to click on App dot r.</p>
<p>And then you want to right click on the raw button right here.</p>
<p>And then you want to click on the safelink s, and then select a suitable position where you want to save the file.</p>
<p>And because I already have it, I will just click on Cancel, but if you don't have it yet, click on the Save button.</p>
<p>Okay, so let's open up the app dot our file right inside the our studio.</p>
<p>Okay, so before we begin a credit to Winston Chang for developing this template by which we greatly modified and simplified to make this app dot our file.</p>
<p>So if you want to check out the full version, go ahead here, links are provided here.</p>
<p>Okay, so in this simplification, we're going to start with the baby steps.</p>
<p>So this web app is an interactive web application whereby it will accept input values in the form of text, primarily the given name and surname.</p>
<p>So let's have a look.</p>
<p>Okay, so the app will accept input which has the given name and the surname Okay, so let's go ahead and type the given name john and insert name is still okay, and so the name john doe will appear in the output here and the name of the app this my first app, you can also modify this to your own liking, okay, and in this example, we have three navigation bar so we intentionally left it blank here, according to the original template by Winston Chang.</p>
<p>Okay, so the code that we have is located on the nav bar dot one so a point in notice that you can also create several web apps inside different navigation bar.</p>
<p>Let's say that you want to modify the name like let's say given name is Jennifer.</p>
<p>So then you'll see that the name is automatically updated.</p>
<p>So notice that there is no Submit button and whenever you type in an updated name, it will automatically update the results.</p>
<p>So in our they implement reactive, let's have a look shiny, reactive, reactive expressions, reactivity and overview, okay, so it's based on the principles of reactive programming, which is used by the shiny package.</p>
<p>So we're not going to go into detail.</p>
<p>But if you're interested, I can also provide the links in the file as well.</p>
<p>concepts about reactive programming used by SHINee.</p>
<p>Okay, so I'm going to provide the link for you, here.</p>
<p>Okay, so a moment ago, we have taken a look at how the web application will look like, which is the end outcome of this code.</p>
<p>So let's look under the hood, what does the code looks like? Okay, so in the slides, I've shown to you that it comprises of three components.</p>
<p>So let's have a look.</p>
<p>So the first component is the UI is right here.</p>
<p>So it's on line 19, until lines 43k, lines 19 until lines 43.</p>
<p>This is the UI or the user interface, and then a lines 47 until 52 is the server component.</p>
<p>So you're going to notice that we're not doing anything much here.</p>
<p>We're just displaying the results.</p>
<p>And so the code is very concise.</p>
<p>And the third component is the shiny app function.</p>
<p>So this thing will piece together the UI and the server.</p>
<p>So it's essentially just saying that, okay, this part here is the UI.</p>
<p>This part here is the server and fused in both to create a shiny app object.</p>
<p>Okay, so that's all there is to it at the conceptual level.</p>
<p>So let's have a look at the components inside the UI object.</p>
<p>Okay, so here is using inside the fluid page tag, it's using the theme argument, and it's telling that we want to use the C raelian.</p>
<p>theme.</p>
<p>Okay.</p>
<p>And the C rolling theme is the blue theme that you've seen a moment ago.</p>
<p>Let's say I want to change it to United.</p>
<p>And I can click on the reload, or I need to save it first.</p>
<p>And then I'll click on the reload, and then it changes to the United Can I want to change to say Yeti, save it, and then it becomes the Yeti theme.</p>
<p>So maybe you're wondering, what's the available options for you.</p>
<p>So if you search for shiny themes in Google key, the first results and just click on it.</p>
<p>So here, this is how a civilian looks like, if you like that you could type in zulian there's Cosmo Cyborg darkly, paper, lumen journal, flatly readable? sandstone, simplex, slate, Space Lab, superhero, united and Yeti.</p>
<p>Let's try superhero.</p>
<p>Okay, so it's john doe.</p>
<p>Okay.</p>
<p>There you go.</p>
<p>By just default back to civilian.</p>
<p>So let's envisage the code as modular components.</p>
<p>So you're going to see that inside the UI, you're going to have a fluid page, you can within this fluid page, you're going to define the theme.</p>
<p>And inside the fluid page, aside from the theme, you're going to have a navigation bar page, right? So the navigation bar page is right here.</p>
<p>It's this bar.</p>
<p>And so the name of the app is my first app.</p>
<p>So this is the name of the navigation bar page.</p>
<p>Inside the nav bar page, there is the tab panel.</p>
<p>Okay, so tab panel comprises of nav bar, one nav, bar, two nav, bar, three can inside and out more.</p>
<p>One, you have the sidebar panel right here to the left, right, you have here sidebar panel, and your sidebar panel contains tag h3, h3 is the heading third level heading input.</p>
<p>And then text input is the given name.</p>
<p>And the text input is the type of input.</p>
<p>So if you change this to something else, it will look differently here.</p>
<p>And there are a lot of widgets, okay, so you can find what you want.</p>
<p>You can shop for what widget you like, and then just replace it right here in the code.</p>
<p>Okay, so the given name is right here, displayed here.</p>
<p>And then this thing here is the default value.</p>
<p>So let's say that I could type in john doe, and let's save it and reload the app.</p>
<p>So you see that john doe will automatically by default appear in the text box, okay, but I can also leave it blank as well.</p>
<p>Right.</p>
<p>So this is the contents of the sidebar panel.</p>
<p>So the sidebar panel will accept The input right and then the main panel is right here where we see header one output one john doe, which is the result.</p>
<p>So in main panel one, right Heather one is inside the h1.</p>
<p>So h1 is the tag, which is the biggest tag available.</p>
<p>And h4 is a smaller tag, right? So we have in order of from big to small, we have h1 and h2 h3, h4, right.</p>
<p>So for the input here, we use h3, if we change it to h1, it will be bigger.</p>
<p>It'll be the same size as the header one here, but it's too big.</p>
<p>So I'm going to change it to just h3 we couldn't even make this a stream as well.</p>
<p>Right, so you've got a little bit bigger for the output one here.</p>
<p>Right, so you can play around with changing the options here.</p>
<p>Okay, and so verbatim text output is simply a text box that will return the output value.</p>
<p>So it's just a simple text box, and then the nav bar to nav bar three, as we have previously mentioned, it is intentionally left blank.</p>
<p>Okay, so there's, that's all there is to the UI.</p>
<p>But the confusing part is how does UI and server interact? How do they send information back and forth? Right? How does UI send the input value to the server? And how does the server accept the input value? Okay, let's have a look right here.</p>
<p>So notice that the text box has this thing called text one.</p>
<p>txt one right in the given name, okay.</p>
<p>And a surname is txt two, okay.</p>
<p>Now, this stat make a note of that, how about I put it in the comments t x T one and T x T two, okay, and make a note of this to t x t out.</p>
<p>txt or UT okay.</p>
<p>So, these two will be sent to, to the server TFT to will also be sent to the server t x t out is generated from the server.</p>
<p>Okay, so let's go back to the slides.</p>
<p>Okay, why don't I create a new slide.</p>
<p>So let's duplicate this slide.</p>
<p>So let's call this the first web app.</p>
<p>And we're going to modify this to reflect the contents of this web app.</p>
<p>So the input data is txt one.</p>
<p>And txt to write and the output is txt out, right.</p>
<p>So it will send txt one and 62 to the server.</p>
<p>And so actually, the server sends write txt out and the TTL will be displayed.</p>
<p>displays.</p>
<p>txt out.</p>
<p>So here txt one and txt two will be sent to the server txt one and txt two here is input dollar sign txt one and input dollar sign txt to Okay, and so the question is, how does it send it as a txt out, it's right here output dollar sign txt out, and it's going to use this function called render text.</p>
<p>Okay, so there's several render function like render table render text, right that you can modify.</p>
<p>So you can also find out from the SHINee documentation, okay, so this output txt out, what is essentially does is it will use the paste function to combine TF T one and T two and separated by a MP space.</p>
<p>And then it will produce the result as the concatenated text of TF T one and T two inside the txt out variable.</p>
<p>And then this variable will be called from within the verbatim text output, and then it will display the text inside the text box.</p>
<p>That's all there is to this shiny web application, it will seem a bit confusing, but if you get the concepts straight, it will be very simple.</p>
<p>And you could create any web application to your own imagination, you can make this web application data driven, you could ask input, you could upload a file of the input data and then the input data will be sent to the server right and then in the server, you could create a machine learning model and then once the machine learning model is built, it would then relate a results back into the UI and then the UI will display the predicted results.</p>
<p>Okay, so this will be very powerful as a model deployment approach for your machine learning model can there's several tips and tricks which we use in our research lab, and we can share this in a future video.</p>
<p>And so if you're finding value out of this video, please smash the like button.</p>
<p>Okay, so let me recap this process.</p>
<p>In summary, this app Our file will contain three components the UI component, which is the user interface, it will accept input, which is the txt one and txt two, which corresponds to the given name and the surname.</p>
<p>And when you input the given name and surname, it will be sent to the server.</p>
<p>And then the paste function will combine tasty one and txt two and put it inside a txt out variable.</p>
<p>And then this TFT out variable is embedded inside the verbatim text output, which is a text box on the UI.</p>
<p>And as a result, you will see the input values that you typed in displayed in the text box.</p>
<p>Okay, so this first web app, which is essentially starting from the basics, so nothing fancy here, just a simple web app where you can type in the name, the first name, last name, and then it will display the result.</p>
<p>Okay, so in future videos of this series, called the web app in our we're going to have several other videos.</p>
<p>And if you have ideas on what application you would like us to develop, let us know.</p>
<p>So please comment down below, and I'll see you in the next one.</p>
<p>Okay, so this video represents the second episode of the web apps in our series.</p>
<p>In the first video, we covered how you can develop your very first shiny web app, and the web app allows you to enter the first name and last name, and the web app will display the output for a sample.</p>
<p>If you enter the first name as john and the last name as Doe, then the output panel will then output john doe.</p>
<p>So in this video, we're going to show you how you can develop your second web app in R.</p>
<p>And so the web app today is really quite simple.</p>
<p>The web app will display a histogram of the air quality data set, particularly the ozone levels, and the user will be able to adjust the bin size, and then the histogram will adjust accordingly.</p>
<p>Okay, so let's get started.</p>
<p>So what you want to do now is go to the data Professor GitHub, so click on the code folder, and then click on the shiny folder, and then click on the 002 histogram.</p>
<p>And then what you want to do now is click on the app dot r, and then right click on the raw link, and then save link as and then save it to a desired destination.</p>
<p>So since I have already downloaded the file, so let's open up the app dot our file.</p>
<p>So why don't we go ahead and run the application.</p>
<p>So as you can see, the web app has the title as the ozone level and the side panel shown on the left as the number of bins as a slider input value.</p>
<p>So you can adjust this by sliding to the left or right and then the resulting histogram will be updated automatically in real time.</p>
<p>So let's say that we adjusted to seven bins, and you will see that in the histogram, there will be a total of seven bars.</p>
<p>If you adjusted to 12, then the number of bins or the number of bars will then be adjusted to 12.</p>
<p>So what is the bin and then in a histogram is essentially the number of bars and each bar represents a range in the value for a sample from the range of zero to five or zero to 10.</p>
<p>And so if you adjust it to one bar, then you will see only one bar here.</p>
<p>And if you adjust to two bins, you will see two bars, right and etc.</p>
<p>And for a maximum of 50 bars.</p>
<p>Okay, so let's go back to the code.</p>
<p>So in this app dot our file, you will see that on line number nine, it essentially loads the shiny library and line number 10 will load the air quality data set into the memory.</p>
<p>And I have already pin the UI in red here.</p>
<p>And the server in red, and the shiny app function in red.</p>
<p>So as in the previous video, I have already mentioned that the shiny app has essentially three major components consisting of the UI component, which is the user interface and the server component that will accept the input value from the UI, and it will do some processing as shown here.</p>
<p>And finally it will generate the output and the output will then be sent back to the UI for display in the main panel.</p>
<p>Okay, so let's recap that again.</p>
<p>So this UI is the user interface and it will allow you to specify the name of the title panel here which is specified as also level.</p>
<p>So let's have a look.</p>
<p>So ozone level is specified by the title panel.</p>
<p>So you can modify this name if you like.</p>
<p>Okay, so let's say you want to call it just ozone, and then you have to save it and then re Load the app can and the app will then be called ozone.</p>
<p>Okay.</p>
<p>Okay, so this is the title panel here.</p>
<p>And the next block of code here will be the sidebar layout.</p>
<p>And the sidebar layout will allow you to specify the sidebar panel and inside the sidebar panel will then be a slider input.</p>
<p>And the slider input is essentially the number of bins, right number of bins in the UI, and it will have an input ID of bins, which the server component will recognize.</p>
<p>Okay, I'm going to show you in just a moment.</p>
<p>And so the minimum value here is one and the maximum value of the band is 50.</p>
<p>And the default value is 30.</p>
<p>So you see here that the minimum is one, the maximum is 50.</p>
<p>And the default value is 30.</p>
<p>So you can adjust the maximum to say 40.</p>
<p>And the fall, you can test it with 20.</p>
<p>And then we will save it and reload the app can and you're going to see that the web app automatically updates to 140.</p>
<p>And with a default of 20.</p>
<p>Okay, and you when you slide it, it'll update as before.</p>
<p>So here you can see that the step size is one because when you slide the button, it will incrementally increase by one.</p>
<p>Let's say that you want to modify the step size to another number.</p>
<p>Can you do that? Yes, you can.</p>
<p>So you want to specify step to be equal to let's say, two.</p>
<p>And the minimum you want, adjust it to zero, save it and reload the app.</p>
<p>And here now the step size becomes 2k.</p>
<p>So 18 and then you move it it becomes 20 you move it it becomes 22k.</p>
<p>So you notice that I've also modified the minimum to be zero because if it's one then a step size will be 13579.</p>
<p>But if you make it into a even number, then the step size will be also even number Okay, so let's have a look if the step size is one, it will be 135 right it will be 135.</p>
<p>So I cannot select 20.</p>
<p>Okay, so it has to be only odd numbers.</p>
<p>So if you want it to be even number then you want to put the minimum to become zero.</p>
<p>Okay.</p>
<p>So here now, you can even make the step size to be five.</p>
<p>Right? 05 1015 2025 30, right.</p>
<p>Okay, so notice that the slider input has an input ID of bins, and let's go into the server component.</p>
<p>And let's find bins where spins, spins, it's right here and bins is right here.</p>
<p>Okay, so the server component will have two bins, the input bins, and it will be the value of the argument and breaks, okay, so it will allow you to specify the number of bins in the histogram and x will be the air quality data set.</p>
<p>And then we use the dollar sign to specify the column called ozone.</p>
<p>Because in air quality data set, let me stop the shiny app.</p>
<p>First, let's have a look air quality dollar sign.</p>
<p>And then notice that you have ozone you have solar you have when you have temperature month.</p>
<p>They Okay, so we specify ozone.</p>
<p>And we'll also notice that also on has some missing data.</p>
<p>Right, it has some missing data here showing us and a the what we're going to do with the missing data is to omit it from the data set using the NA dot omit function and then save it back into the x variable.</p>
<p>Okay, and then the bins variable will then determine what is the minimum value of the bin and what is the maximum value of the bin.</p>
<p>Okay, so moving on to the next function is the histogram function where x is the input data, which is the air quality or sown column and the breaks will be equal to the number of bins that we specify here can so the color will be discolor, which is bluish color, and the border will be black.</p>
<p>So this is the blue color mentioned in here and the border is black.</p>
<p>So we see a black line and the x label is also on level.</p>
<p>So the x label is right here.</p>
<p>And then the main is histogram of ozone level.</p>
<p>So main is right here, right? So you can just label or also the main text as well.</p>
<p>So in this output dollar sign dist plot, we will use the render plot and then this will generate an output called output dist plot.</p>
<p>And then we're going to know this.</p>
<p>If we screw up to the main panel of the UI component, the plot output function We'll have an output ID equals to this plot.</p>
<p>Okay, so the name, this plot here and this point here are the same object.</p>
<p>So the server will generate this output object called this plot and sends it to the UI component for display on the main panel.</p>
<p>So the main panel is located right here.</p>
<p>Okay, so finally, the shiny app function will fuse together the UI component and the server component.</p>
<p>So you're going to see that the code communicates between the UI and the server, right, so the UI will accept the input, which is the number of pins and it will send a number of pins to the server component, and the server component will generate the histogram plot.</p>
<p>And the histogram plot will be contained within this output this plot and it will be sent to the plot output function in the main panel of the UI.</p>
<p>And so you will see the resulting histogram being generated.</p>
<p>And if you adjust the value of the input bin number, then the plot will also update automatically using the reactive function of SHINee.</p>
<p>Okay, so you can customize the color if you like, let's make it 003366.</p>
<p>Okay, so it's dark blue? Or what if we just call it blue? Or how about let's use red.</p>
<p>Okay, so the plot will become red, if we use green.</p>
<p>So the histogram will also be green.</p>
<p>So here, you can customize the color to your own liking and experiment.</p>
<p>And don't forget to upload this to your GitHub so that you can start building your portfolio for data science projects, and then you're going to have several repository in your GitHub in no time.</p>
<p>Congratulations, you have built your second shiny web application in our Okay, so this is the third episode of the web apps in our series.</p>
<p>So today, we're going to build a play golf web application.</p>
<p>So probably you're wondering what is a play golf application.</p>
<p>So the play golf web application that we're going to build today is going to be based on the weather data set provided by the weeka data mining software.</p>
<p>So let's have a look here.</p>
<p>So the data set is a relatively small data set where it has a total of five variables.</p>
<p>So four variables are the outlook temperature, humidity, and when and the class label would be to play or not play golf, which is a function of the weather and the condition, right, like whether it is sunny weather, the temperature is high, whether the humidity is high, or low or medium, and whether there is win or not true or false.</p>
<p>And then the final decision is to either play or not play golf.</p>
<p>Okay.</p>
<p>So before we dive into the code, let's have a look at how this the web application looks like.</p>
<p>Okay, so the web app looks like this.</p>
<p>It's a very simple application.</p>
<p>So the name of the web app is play golf.</p>
<p>And so here there is the input parameters comprising of the four variables that I have mentioned.</p>
<p>The first one is the outlook.</p>
<p>And so the user can select one of three outlook, whether it is sunny, whether there is overcast of cloud, and also whether there is rain or not.</p>
<p>And the second variable is to temperature.</p>
<p>And so this is a slider input, so the user can slide the input value, and then the humidity is also a slider input.</p>
<p>And then windy is either a yes or a no, which is a drop down menu.</p>
<p>And then when you're ready to make a prediction, you just click on the submit button.</p>
<p>Okay, and here you see a prediction is being made.</p>
<p>And the prediction says yes, and then we also see the underlying probability in that the know has a 27% probability.</p>
<p>And the yes has a 73% probability.</p>
<p>And so you could play around with this, right? If, for example, if it is sunny, and the humidity is very high, and the temperature is very high, and there is when should you play golf? No, right? I mean, really, if the temperature is high, it's very humid, and it's very windy and it's sunny, right? Probably not.</p>
<p>Right.</p>
<p>Okay.</p>
<p>What if What if the humidity is low temperature is quite cool, and it's sunny, and it's not so windy.</p>
<p>Would you play golf, right? Yes.</p>
<p>Right.</p>
<p>So there's an 87 probability for Yes, and a 13% probability for No.</p>
<p>Okay, so this is the web app we're going to build today.</p>
<p>So let's go ahead and stop the web app for a moment.</p>
<p>Okay, so what you want to do now is Go to the data Professor GitHub.</p>
<p>And then you want to click on the code directory, and followed by clicking on the shiny directory.</p>
<p>And finally clicking on the 003, play golf directory.</p>
<p>And then click on the app dot our file.</p>
<p>Okay, so what you want to do is right click on the raw link, and then save to file.</p>
<p>So I'm going to save it into the weather folder, save it, okay, it's right here, click on it, make sure that the app works.</p>
<p>Okay, it works.</p>
<p>prediction has been made.</p>
<p>Okay, cool.</p>
<p>So let's just clear up this by pressing on the ctrl and L button.</p>
<p>Okay, so let's have a look under the hood, what does the app dot our file looks like? So the first couple of lines, which is import libraries used by this app dot our file.</p>
<p>So this comprises of the shiny package, shiny themes package, the data dot table library, the our curl library and the random forest library.</p>
<p>Okay, so next line of code would be to create a data object called weather by reading the CSV, which is downloaded from the data Professor GitHub in the data folder.</p>
<p>And the file is called weather dot weeka dot CSV panelists have a look at the data set.</p>
<p>What does it look like? I'll click on the line weather and then I hit on the control and enter button.</p>
<p>And then let's type in weather.</p>
<p>Okay, so this is wanting me to see, let's go with head and then weather.</p>
<p>Okay, and so we see that there are five columns outlook, temperature, humidity, windy and play.</p>
<p>Right.</p>
<p>And let's have a look at the data type of the data set, we see that the outlook has three factor levels play has two factor levels.</p>
<p>So these are categorical label.</p>
<p>No, yes.</p>
<p>And the outlook is overcast, rainy and sunny.</p>
<p>Windy is a true and false humidity and temperature are integers.</p>
<p>And so a random forest model will be created by using the four variables comprising of Outlook temperature, humidity, windy as the input variable, and the play variable here will be used as the output variable or the variable that we want to predict.</p>
<p>Okay, and in the data equals to weather, which is the weather data object here.</p>
<p>And we're going to use number of three to be five lines read.</p>
<p>And because there are four input variables, we're just going to use em try a four.</p>
<p>Okay, so let's try building a model and the model has been built.</p>
<p>And let's apply the model for prediction, shall we, I mean, just to test that the code is working properly.</p>
<p>So let's try applying the model on the input file that I have previously mentioned about.</p>
<p>And so we're going to run this line and putting the data into the variable called test can and we're going to assign the factor because if we don't do it, then it'll provide an error.</p>
<p>So before we run this line of code, let's just try to make a prediction model.</p>
<p>And we should be able to see a error coming up.</p>
<p>Okay, so we got this error error in predict random forest type of predictor in new data do not match.</p>
<p>So what we notice is that if we type in the str, and then we type in weather, and then we notice that the outlook has factors with three level, but if we type in str, and then the test variable, notice that the outlook has a factor of only one level.</p>
<p>And this is because the input data has only one line of data, which is essentially one row of data.</p>
<p>And so the outlook is only sunny for the prediction being made has only one role.</p>
<p>And but in reality, it should have three levels of the factor.</p>
<p>So we're gonna define that by telling the code that there are three possible factors there are overcast, rainy, and sunny.</p>
<p>So let's run that line of code and then run the prediction again, okay, and it works.</p>
<p>And then print outputs.</p>
<p>And here we go, we got the prediction, which is exactly what is going to be displayed on the web application.</p>
<p>Let me show you.</p>
<p>Right, we make the prediction, and shown here.</p>
<p>So this table you see here is shown right here.</p>
<p>So the model works, and let's go to the other lines of code.</p>
<p>So the next one would be the user interface.</p>
<p>Right.</p>
<p>As I mentioned in previous video, the user interface represents the first component of the shiny web app.</p>
<p>And this is followed by the second component, which is the server and then this is followed by the third component, which is the fusion of the user interface and the server component using the shiny app function.</p>
<p>So let's talk about the UI.</p>
<p>So this UI object makes use of the fluid page function And we're going to use the theme equals to the shiny theme united.</p>
<p>And so the United theme will give the buttons a red color.</p>
<p>So if we change it to thoroughly and then we're going to have the thruline color theme, which is a bit blue.</p>
<p>Okay, so please refer to the first video of the web apps in our in order to see the selection of web templates that you can choose from.</p>
<p>Okay, so let's run the app again.</p>
<p>And I'm going to put the app just about right, right here.</p>
<p>So the header panel is play golf.</p>
<p>And so this is right here, play golf.</p>
<p>So if you want to change the name, feel free to do so.</p>
<p>And then the next one is the sidebar panel.</p>
<p>So the sidebar panel will accept the input parameters is located to the left, and there will be a total of four input.</p>
<p>And so the first one is select input, which is a drop down menu.</p>
<p>And if you click on it, you get three selections, Sunny, overcast, rainy, and when you hover on the drop down menu on sunny it will secretly under the hood, select the sunny object, and if you select on the overcast also, it will under the hood be equivalent to the overcast object.</p>
<p>If you select on the rainy it will be equivalent to the rainy object and the default is to select rainy, right here we'll select rainy as the default What if you change it to sunny now let's change the value to be a high value, let's say like 85 and humidity to be 95.</p>
<p>And it's windy, that's true.</p>
<p>Reload the app again, right.</p>
<p>So high temperature high humidity windy, Sunny, don't play golf.</p>
<p>Okay, so here you can change the default value to your liking.</p>
<p>Okay, so we have mentioned about the three data objects four here, Sunny, overcast and rainy.</p>
<p>So keep that in mind, we're going to make use of data in the server function.</p>
<p>And note that when we will refer to it later on in the server function, it will be referred to as input dollar sign outlook input dollar sign temperature input, dollar sign humidity and input dollar sign windy.</p>
<p>Here, why don't we just scroll down and have a look here input dollar sign outlook input dollar sign temperature input dollar sign humidity input dollar sign windy, okay.</p>
<p>And then let's move back up.</p>
<p>Notice the spelling here using the small letter not the Capital One.</p>
<p>So the Capital One Here are the label.</p>
<p>So it's exactly what we're going to see in the web application outlook with the colon is right here on the label.</p>
<p>Okay, actually, you don't have to type in label if you don't want to, we could just you know, delete it, and it will give the same results.</p>
<p>It's just implied, okay.</p>
<p>But if you want to add the label argument, you could feel free to do so.</p>
<p>Right? But if you do it for one, well might as well do it for all.</p>
<p>So that would actually make the code looks a bit more easier to read.</p>
<p>Right.</p>
<p>So let me see here that okay, this is the object name, Outlook.</p>
<p>And the label is outlook with a capital O reload the app.</p>
<p>Here you go.</p>
<p>Right, it works as usual.</p>
<p>So here, this outlook here is that outlook object.</p>
<p>And this temperature here is the temperature object.</p>
<p>And this action button here is the submit button.</p>
<p>So this Submit button is added in order to overcome the reactive function.</p>
<p>So we're just at the familiar Submit button so that users can initiate the prediction process when they feel ready to do so instead of having the web app being reactive and making the prediction spontaneously upon sliding up and down of the input values.</p>
<p>Because when it's reactive, if you move it by one notch, and then you let go of the mouse, it'll make a prediction.</p>
<p>But for this one with the submit button, no prediction will be made until you actually click on the submit button to actually this might be a good thing on the server side because the server will work a bit less if the prediction being made is made only once versus if it is in the reactive mode.</p>
<p>If you slide the input value and you just change your mind later on.</p>
<p>Then prediction will be made at each point off the changing of the input value of the slider here or even the drop down menu, right.</p>
<p>But we do it once with the use of the submit button.</p>
<p>Okay, and that's it for this left sidebar panel.</p>
<p>And then the main panel here will display the result from the output generated by the server function.</p>
<p>So we're going to talk about that in just a moment.</p>
<p>So why don't we note that the output being generated by the server component will be called contents and table data.</p>
<p>Okay.</p>
<p>Okay, so let's hop on to the server function which is the second component.</p>
<p>So in this data set in Put variable it will comprise of the first component is it will create a data frame which will accept four input values from the web application compressing off the outlook temperature, humidity windy, which is right here outlook temperature humidity windy, and then it will combine it with the play variable, which is the fifth column of the original data set and then it will transpose the data set it will rotate it in will transpose it and then write a input dot CSV file, it will read the input that CSV file back in into the test variable.</p>
<p>And then it will apply the factor function in order to tell that the outlook has three levels.</p>
<p>And finally, a prediction will be made using the model generated earlier by means of the random forest and apply the prediction model to predict the input values from the user.</p>
<p>And once the prediction is made, it will be sent from here into the output dollar sign table data as the function data set input right here.</p>
<p>And then it's going to render the table as we will see in the web application.</p>
<p>So the table that is being rendered will be right here, which comprises of three columns to prediction the know in the Yes, probability k and this status output textbox is just essentially this box right here.</p>
<p>So if we load the app for the first time, it will just say server is ready for calculation.</p>
<p>And if we click on the submit button, the text will change to calculation complete and it will be followed by the prediction results table.</p>
<p>Okay, so note that there are two output being generated right here output dollar sign contents, output dollar sign table data.</p>
<p>So these two outputs will be sent to the UI component right here, table data and contents, table data will be displayed as a table using the table output function.</p>
<p>And the status of the prediction whether it is ready for prediction or prediction has been made will be displayed by the verbatim text output function K.</p>
<p>And this is just a label of the status output text box shown right here that we're going to have the H three font size, I mean, if you want to change it to H to make it a bit bigger than you will notice that the font will become bigger, right? So I'm just going to make it back to h3.</p>
<p>Okay.</p>
<p>So that's all right.</p>
<p>And then the last component shiny app function, which is fused the UI and the server together again, you have all of this in 121 lines of code.</p>
<p>And so nothing fancy here, just a simple web application that you can create using the shiny language.</p>
<p>Okay, so this video represents the fourth episode of the web apps in our series.</p>
<p>And today we're going to cover about how we can develop a Iris predictor, which is a machine learning model in the background.</p>
<p>And the web app allows the user to select the input values for the four input parameters and press on the submit button and make a prediction.</p>
<p>So without further ado, let's get started.</p>
<p>Okay, so the first thing that you want to do is go to the data Professor GitHub.</p>
<p>Okay, once you arrive here, you click on the code link, and then find SHINee, and then click on the serial zero for Iris predictor.</p>
<p>So what you want to do now is to download the first three files comprising of the app numeric dot, our app, slider dot r and the model dot r, because the other three files found below will be generated automatically when we run the code.</p>
<p>Okay, so why don't we just click on each of them manually.</p>
<p>And then for each, right click on the raw button and click on the Save Link As a key and then you select the location in your computer where you want to save the files.</p>
<p>So you do this for all three files, the app numeric that our apps are and the model dot r.</p>
<p>Okay, so I have already done that.</p>
<p>And I will go back to the our studio application.</p>
<p>Okay, so before we begin, let's have a look at what the the iris predictor web application that we are going to develop today looks like so you want to hit on the run app, you need to make sure that your working directory is at the folder where it contains all of the necessary files to be run the one that you have just downloaded.</p>
<p>Okay, and once you have made sure already, you want to click on the run app button.</p>
<p>Alright, so this is what the app looks like.</p>
<p>And it allows you to put in the four input parameters.</p>
<p>And so these are the default values which you can adjust accordingly.</p>
<p>And then when you click on the submit button, the prediction will be made.</p>
<p>And here the prediction is made to be that the input parameter is predicted to be a Iris setosa flower and the probability of it being a Irish atossa is 100% sense, okay, and so if you change the input parameters and so the prediction will also be changed because the input parameter will be feed into the predictive model, which is a random forest.</p>
<p>And then the random forest will perform the classification.</p>
<p>And it has classified this input parameter as a Iris virginica with 100% probability.</p>
<p>So let's have a look under the hood, what does the code actually looks like? Okay, so the first code that you want to open up right now is the model dot r.</p>
<p>So in this tutorial, we're going to pre build the random forest model, and then we're going to load it in, right.</p>
<p>So as you recall, in the previous videos of this channel, we have shown you how you can deploy your predictive model into a RDS file.</p>
<p>And so what you want to do is you develop the model in this model, dot our file, and you save it as an RDS, right? So you're deploying that.</p>
<p>And then you're going to read that in here on line number 15, you're going to read the model dot RDS n, and you're going to give it a name, the name is model, and then we're going to use this model for making the prediction.</p>
<p>So the advantage of this is that the model is already built.</p>
<p>And so there is no additional workload on the shiny application.</p>
<p>So it can just readily read in the model and perform the classification.</p>
<p>So this will be beneficial in the case in which the predictive model will take a long time to build the model.</p>
<p>Okay, so let's have a look at the model dot our file where we will be building the model.</p>
<p>So the first steps that we want to do now is to load in the libraries, which will include the our curl and the random forest.</p>
<p>So the our curl library will allow us to read the data Professor GitHub to download the iris data set, and then the random forest will be used to create the prediction model.</p>
<p>And we also need the carrot package in order to do the data splitting.</p>
<p>Okay, so Iris here will mean that we will create a data object called Iris because we're going to read in the CSV, which will retrieve the CSV file from the data Professor GitHub, and the file is called Iris dot CSV, okay, and it will use the carrot package to perform data splitting, using a ratio of 8020 to 0.8.</p>
<p>Here is to 80% split, which will go into the training index, and then we will subsequently use the training index to create a training set in which it will perform slicing of the original Iris data frame, and then the remainder 20% will go to the testing set.</p>
<p>So what we're going to do next is we're going to write the training set and the testing set out into the CSV files, right, because that would help to remedy possible shuffling of the data that will go into the training set and the testing set, so it will allow reproducibility in the future.</p>
<p>So in the future, we can just read in the training dot CSV file, instead of performing the data splitting again, right.</p>
<p>So here, we're going to read in the training dot CSV file and give it the same name, which is the train set Canada, we're going to delete the first column, which is the index number.</p>
<p>And then we're going to build a model and assign the built model into the model data object.</p>
<p>And once a model has been built, we're going to save it as the RDS file.</p>
<p>So the we're going to deploy the model into the RDS format.</p>
<p>So in this random forest function code, we're specifying that we want to predict the species of the iris flower.</p>
<p>And we're going to use all four input parameters and the data set, we'll be using the training set for making the model and then we're going to assign a entry value, which is the parameter of the random forest to be five Heinz red, and we're going to assign the M try parameter to be four, right, and then we're going to assign a true value for the importance argument, okay, and so so while you want to do is you want to run all of this blocks of code, so you could just Ctrl A, select everything and then Ctrl, enter.</p>
<p>Okay, and then the data will be read, and then a model will be built, and it will be saved as the model dot RDS.</p>
<p>Okay, so this concludes the model dot our file, and then we're going to close that.</p>
<p>And then we're going to open up the second file, which is the app gnumeric dot r k.</p>
<p>So let's have a look.</p>
<p>The first few lines will be importing the necessary libraries, which will be the shiny library, the data dot table, the random forest package, and then we're going to read in the model that we have built in the previous step.</p>
<p>And we're going to assign it into a model object, right.</p>
<p>And then like in previous video, the shiny web application will contain three components.</p>
<p>So the first component being the UI, and the second component being the server.</p>
<p>And the third component being the shiny app function, which will essentially piece together the UI and the server.</p>
<p>Okay, so let's have a look at the UI.</p>
<p>And we're going to open up the web application and have a look right at the same time.</p>
<p>And for readability of the code, I would just add additional enters to it and new line to it.</p>
<p>So that when I open up the web browser, concurrently The values here won't be hidden.</p>
<p>Okay? Save it and go back to the web application.</p>
<p>Alright, so here, the name of this web application is called Iris predictor.</p>
<p>And so it is in the header panel here.</p>
<p>So we put in the iris predictor, if you want to change the name, feel free to do so right here.</p>
<p>And then we're going to have the sidebar panel, which is on the left, and then we're going to have the main bar panel, which is on the right, so as always, the left or the sidebar panel will take in the input parameters, and then clicking on the submit button, which is right here, it will send the input parameters to the server function, and the server will use that input parameters to feed it in to the predictive model, which is the random forest model and make a prediction.</p>
<p>And once your prediction has been made, the resulting output value generated will then be feed back into the main panel right here.</p>
<p>And then the results will be displayed in the table data, which is going to be occurring right below this text message.</p>
<p>So the table data will be shown right here, which is the prediction being made.</p>
<p>Okay, so in the input parameters, we're going to use the HTML tag and inside we're going to assign a size of the header to be h3 right, and a name will be input parameters right here.</p>
<p>So further showing the versatility of the shiny application framework.</p>
<p>So notice that the s and l are capital letter, and this is the ID of this input parameter sepal length, and it is case sensitive.</p>
<p>So we have to type it in exactly S is when we're going to use it in the next step.</p>
<p>So it's going to be like input dollar sign, and then CBOE dot length.</p>
<p>And then this will be the input parameter, which the server function will be using as the data to be fed into the random forest model.</p>
<p>Okay, and so the label here will be sepal length.</p>
<p>And the label means right here, the label and the value is the default value, which is five and here is five.</p>
<p>So if you change the default value to 5.1, and you save it, run the app again.</p>
<p>So you see that the 5.1 will be updated right here in place of the 5.0.</p>
<p>Okay, so the same thing will be for the sepal width, petal length and petal width, right with the label and with the value, which is the default value right here.</p>
<p>And then the next block of code here is the action button function.</p>
<p>And this will be the submit button.</p>
<p>So it will overwrite the reactive function in which when there is no Submit button, every time we modify the numbers in here, a prediction will be made.</p>
<p>So that would put a heavy load onto the server, because every time that you update the value here, a prediction will be made.</p>
<p>So imagine that you update the values 10 times 20 times and 20 predictive models will be created.</p>
<p>Whereas in a situation where you have the submit button, you can spend all the time or as many times as you need to update the values, right? Let's see if I went to and then I changed my mind, I want to have it 4.9.</p>
<p>So do this 10 more times.</p>
<p>And so the prediction model will not be built, right.</p>
<p>So it's going to wait for you until you click on the submit button and then the prediction will be made.</p>
<p>Okay, so this will be more economical on the server side.</p>
<p>And also for familiarity, where we normally would click on some button in order to initiate the process of the prediction.</p>
<p>Okay, and then the following block of code main panel will be right here.</p>
<p>So in the tax label h3 status output, it will be this part.</p>
<p>So notice that this block of code is exactly the same as the HTML block of code.</p>
<p>So I'm just showing you the versatility of the shiny web application.</p>
<p>And you could use either one, okay, but this is the shiny way of doing things, right.</p>
<p>So let me show you by putting it right here.</p>
<p>And then I'm going to comment that out and put in the APR parameters here and then replace the value inside.</p>
<p>Okay, reload the application, right, and then it looks exactly the same, right.</p>
<p>So you can do it both ways, right, and then the following text box shown here will tell you that the server is ready for calculation.</p>
<p>So this will be displayed upon loading of the web application.</p>
<p>And upon clicking on the submit button, the value will be changed to be calculation complete.</p>
<p>Okay, so this will be on the server side.</p>
<p>So I will show you in just a moment.</p>
<p>Okay, so we finished with the UI component.</p>
<p>And now let's go on to the server component.</p>
<p>And so here we're going to load in the function, okay, so this block of code here will be the input parameters, which will be obtained from the UI component where the user will input the input parameters and click on Submit button.</p>
<p>And upon doing that, all of the input parameters will come in as shown in this block of code here.</p>
<p>And this block of code will essentially generate the input CSV file, which will be read into the test object and then apply the model to make a prediction on this test object.</p>
<p>And once the prediction has been made, this block of code data set input will contain the prediction and the prediction value will be inserted right here, right and it's going to be encapsulated by a output table data variable name and then This thing and then the input dollar sign, and then the output dollar sign table data will be sent to the main panel in the UI to be displayed.</p>
<p>So it's right here, right.</p>
<p>So this one will come from the table data right here, table data, right this highlighted in blue, and it will be coming from the prediction results table, right, which we use the render table function here, and the data set input here will contain the prediction which is coming out from the output data object.</p>
<p>Okay, so let me go specifically line by line here.</p>
<p>So a data frame will be created, and then name will be the name of the Heather variable name on the first row, and then the values will take and the input parameter value from the UI.</p>
<p>So input dollar sign, sepal length, sepal width, petal length, petal width will come from the input text box right here 5.1 3.6 1.4 2.2.</p>
<p>So these text box will be the input dollar sign, sepal length, sepal width, petal length, petal width, okay, and then we're going to create a data frame.</p>
<p>And once we have done that, we will write it out as a input dot CSV file.</p>
<p>Now we're going to read it back in, and then we're going to put it into the test object, and then we're going to create a output object and a data frame will be created.</p>
<p>And we apply the prediction function in order to make a prediction using the random forest model on the input test data.</p>
<p>And once the prediction has been made, we will also tell the probability in three digits Okay, and once a prediction has been made, it will then be sent to this output data object and it will print it out and it will be representing the data set inputs, and this data set input will be inserted into the render table function, and a table will be generated to show you the output prediction results shown right here.</p>
<p>Right.</p>
<p>Okay.</p>
<p>So that's essentially it for this Iris predictor in the numeric form.</p>
<p>So let's close this and hop on to the next one.</p>
<p>Okay, so now we're going to proceed with the app slider version.</p>
<p>And before doing so you want to clean the workspace environment.</p>
<p>So click on the broom button.</p>
<p>And then after you have done that, then you want to click on the app, slider dot r and then Ctrl, a, and then Ctrl, enter.</p>
<p>Right, and then the web app will be loaded.</p>
<p>So you see that now instead of a tap spots where we put in the numerical value, you're going to have a slider, right and then you click on the input parameter by sliding here, and then after you're satisfied with the input values, then you will click on the submit button, and then the prediction will be made.</p>
<p>And as always, it looks exactly the same, but the only difference is the input parameters will have the slider bar instead of the textbox.</p>
<p>Okay, so let's have a look under the hood.</p>
<p>So what new code did we add to this file, so we've added line 1718, and 19.</p>
<p>And then we've also added two new arguments, which is the minimum and the maximum argument into each of the inputs.</p>
<p>And we also change the name from numeric input into slider input.</p>
<p>And that's essentially it, we just change a couple of lines of code and the web app will look like this.</p>
<p>Instead of a numeric text box, we're going to have a slider bar.</p>
<p>So the value of the minimum here will be taken as the minimum function and then the train set dollar sign simple link, right.</p>
<p>So I don't have to manually put in the minimum value or maximum value, but I will do this programmatically.</p>
<p>So I'm going to use the minimum function and inside the minimum function as the argument, I'm going to say, Okay, I want to have the train set object.</p>
<p>And I want to have the simple link column.</p>
<p>And I want to know what is the minimum value, right, it's going to be like this.</p>
<p>So let me close this, and I'm going to read in the file.</p>
<p>So let me show you how it looks like.</p>
<p>And if I run the train set, it will look like this.</p>
<p>And then I'm going to run this line and then notice that the first column will be gone, right, I don't want the index to be shown.</p>
<p>So I just deleted out.</p>
<p>And then when I say train set dollar sign sepal length, where they get will be this, so it's going to be the values of only the first column.</p>
<p>And upon adding the minimum function in front, I'm going to get the minimum value.</p>
<p>And if I use the maximum function, I'm going to get the maximum value of this column.</p>
<p>So the minimum is 4.3.</p>
<p>And the maximum is 7.9.</p>
<p>So instead of putting in the values manually, 4.3 7.9, I'm going to do it programmatically, and it's going to be so much easier, right? And then I just put it in right here.</p>
<p>And that's all for modifying the code and everything else works exactly the same.</p>
<p>And you get a new feel to the web application and it's not that difficult.</p>
<p>Okay, So play around and let me know what kind of web application you want to be made and Or the input data that you want me to use for making the web app.</p>
<p>Okay, so today represents the fifth episode of the web apps in our series.</p>
<p>And today we're going to cover about how you can develop a BMI calculator.</p>
<p>So if you're wondering what is a BMI, so essentially, BMI stands for body mass index, and it is computed by dividing the weight in kilograms by the heights in square meters.</p>
<p>So for example, if you weighed 70 kilograms and you are 170 centimeters tall, then you would first have to convert the height to a meter.</p>
<p>So 170 centimeters would then become 1.7 meters.</p>
<p>And according to the equation, you would take your weight, which is 70 kilograms divided by 1.7 meter squared, okay, so let me calculate that.</p>
<p>So 1.7 times 1.7, would be 2.89.</p>
<p>And if I weighed 70 kilograms, divide that by the squared heights, then my BMI would be 24.2.</p>
<p>Okay, so let's have a look at the scale of the BMI in adults.</p>
<p>So if you have a BMI below 18.5, then it would mean that you are underweight.</p>
<p>If you have a BMI in the range of 18.5 and 24.9, then it means that you have a healthy weight.</p>
<p>And if your BMI is between 25 to 29.9, it means that you are overweight.</p>
<p>And if you have a BMI of greater than 30, then you are obese.</p>
<p>Okay, so in the previous example, a BMI of 24.2 would mean that the weight is a healthy weight.</p>
<p>So without further ado, let's get started in developing our BMI web application.</p>
<p>So you want to go first to the GitHub of the data professor.</p>
<p>And so click on the code folder, find shiny and click on the shiny folder.</p>
<p>And then find the 005 that BMI click on that.</p>
<p>And then you want to download both the about.md and the app dot r into your computer.</p>
<p>So why don't we do that, right, right click on the raw to save link as because we're going to download it into a BMI folder.</p>
<p>We save it there.</p>
<p>And then download the second file, right click on the raw link, safely add as save it to the folder BMI.</p>
<p>Okay, and now we have to upload the folder.</p>
<p>Okay, there you have it, you have two files at that R and about.md.</p>
<p>So let's have a quick look at what this file look like.</p>
<p>So as you show the app dot r is the art code comprising of the three major components, the UI, the user interface, number two is the server.</p>
<p>And number three is the signing out function which fuses both the UI and the server function.</p>
<p>And in the second file, you have the about.md.</p>
<p>So this is written in the markdown language.</p>
<p>And it's going to be used by the app dot our file.</p>
<p>So we're going to see that in just a moment.</p>
<p>So before we dive deep into the our code, let's have a look what the web application looks like.</p>
<p>Click on the run app.</p>
<p>Okay, so this is a simple web application where you can put in your input height and your weight, so the height will be in centimeters and the weight will be in kilograms.</p>
<p>So the minimum value here is 40 for the heights, and 250 for the maximum value, and for the weight, the minimum value is 20.</p>
<p>And the maximum value is 100.</p>
<p>So please note that this BMI calculator is developed for adults and it's not suitable for children.</p>
<p>If you want to develop a BMI for children, then we will have to refer to this second link here.</p>
<p>Okay, so as you notice that when they click on the about link on the navigation bar, it shows the information in the About page.</p>
<p>So originally, the code was written here in markdown language and here in the website.</p>
<p>It displays it as a Normal webpage.</p>
<p>So here you can add boldness to the text, you can add superscript make it stand out as an equation, you could add italic font, right.</p>
<p>So all of this is within the markdown language, right? For example, if you for example, if you use two asterisks, it will mean that the tests will be in bold text.</p>
<p>So meaning that you have to use two asterisks before and after the test, you want to meet both.</p>
<p>And if you use the for hash tag, it means that you are going to use the Heather level for tag, which is the h4 tag in HTML.</p>
<p>And if you're using the greater than symbol here, it means that it's going to display this light gray bar to the left.</p>
<p>So you know that it's a equation.</p>
<p>And if you use one asterisk, then it means that the tax will be in Tillich form, right.</p>
<p>And here we use it for hash tagging in and so it becomes a header.</p>
<p>And then we make the BMI calculator in Italy form by using the asterisk before and after, and even add the links to the website, right.</p>
<p>So the taps that you want to make into a link, you have to put that in bracket and immediately following that, you have to put in parenthesis the URL of the webpage.</p>
<p>And so this is format to like a normal web page.</p>
<p>And so the web application, and so the web application, it's mobile friendly, and you can use it on your mobile phone, okay, it would look something like this on the phone.</p>
<p>And if you click on it, and you get the BMI, right, in my previous example, a height of 170 and a weight of 70, you will get a BMI of 24.2 to 145.</p>
<p>And because we're rounding it, and therefore we get 24.22.</p>
<p>Okay, so this web application seems simple enough, okay.</p>
<p>And so let's dive deep into the code.</p>
<p>Okay, so let's have a look at the code of the app dot our file.</p>
<p>So the first two lines here will be the loading in of the library package of shiny and shiny themes.</p>
<p>And then following that we have the user interface.</p>
<p>So inside the UI optic, it's going to be the fluid page function.</p>
<p>And here, we will define that we're going to use the shiny theme of united and first run the app and have a look.</p>
<p>So here at the nav bar page function shows that we're going to use the name of this navigation bar to be BMI calculator.</p>
<p>And then the tab panel will have the first navigation tab here to be home.</p>
<p>Okay, and inside top panel here, we're going to use the sidebar panel and the main panel.</p>
<p>So as usual, the sidebar panel is right here to the left, and to the right, in the status output, we're going to have the main panel, right so the sidebar panel will contain the input parameters, which comprises of two input parameters, the height and the weight, and we're using a slider input, so you can slide the bar here, and then you get the desired value, click on the submit button, and then you get the calculated BMI value.</p>
<p>Okay, so the slider input here is responsible for this slider button.</p>
<p>And so the name of this slider input is called height here in label height.</p>
<p>And the first one will be the ID of this specific slider inputs.</p>
<p>And so this slider input has an ID of heights, notice the small h and then the second slider input has a value of weights and notice the small W and so these two slider input will then be used in the next step, it will be used by the server function as the input dollar sign weights and input dollar sign heights in order to calculate the BMI, okay, and then the action button function will be the red button that you click to initiate the calculation process.</p>
<p>And so the main panel will have h3 tag here showing the status outputs Okay, and then the verbatim text output will contain the contents ID, which is from the output in the server function.</p>
<p>And in the table output is also from the output of the server function, it is called the table data.</p>
<p>And this is the table data containing the computed BMI value.</p>
<p>So let me recap that again.</p>
<p>So here the slider input, we have to work them height and weight and so it will be referred to as input dollar sign heights input dollar sign weights.</p>
<p>And as the user slides this value, it will adjust the value to the height parameter or the weight parameter and the input dollar sign height value and the input dollar sign weight value will then go to the server function.</p>
<p>I will show you right now, right here.</p>
<p>So we go to the server function in the equation that we're going to create puti BMI.</p>
<p>So here we're taking the input dollar sign weight, dividing it by the in parenthesis, the input dollar sign height divided by 100, right, because we want to convert the centimeters to become meter, so we have to divide the centimeter value by our friends read, and that will then make it a major form.</p>
<p>And then we're going to multiply the height by itself so that we get the squared height value.</p>
<p>And then we're going to divide the weight by the height in order to get the BMI.</p>
<p>And we're going to encapsulate the BMI value inside a data frame so that we can display it in the final output here below in the output contents, it will show that the server is ready for calculation or the server has already completed the calculation.</p>
<p>So this will be modified by the submit button, the red button that we clicked right here.</p>
<p>So when we don't click the button, it will say server is ready for calculation.</p>
<p>But upon clicking on the red button, the BMI will be calculated.</p>
<p>And then in this text box, the text will change to calculation complete kn in the following output results here is called the output dollar sign table data.</p>
<p>And inside here, we're going to use the render table function.</p>
<p>So the results from the data set input will be the computed BMI value right here in the print BMI.</p>
<p>So let me recap again, let's have a look at the web application again.</p>
<p>So this web application will take two input parameters, the height and weight, and they are in the centimeter unit and the height and the weight will be referred to as input dollar sign heights and input dollar sign weights.</p>
<p>And upon clicking on the red button, it will be sent to the server function into this BMI calculator function.</p>
<p>So it will then take the input weights and the input height and perform the calculation and return the BMI value.</p>
<p>And then we put the BMI value into a data frame.</p>
<p>And then we print it out and the results of the BMI is printing out is part of the data set input variable.</p>
<p>And that is called within the render table function of the output dollar sign table data and the output dollar sign table data will go to the main panel right here in the main panel to be displayed in the table output.</p>
<p>And it looks like this right here.</p>
<p>So you see that it's called BMI and then we have to BMI value right beneath it, right.</p>
<p>And that's all there is to building this BMI web application.</p>
<p>So you can play around with this code.</p>
<p>And you can change the default value, for example, the height, you can make it 180 and the value of the weight, you could make it say 75, right and then run the code again.</p>
<p>So the default value then becomes updated to be 180 and 75.</p>
<p>So let's say that you want to update the maximum value to be 300, minimum value to be 50.</p>
<p>And the weight, you want to update it to say 30.</p>
<p>And the maximum would be 120.</p>
<p>And then we load the application and here you see the minimum values and maximum values are updated accordingly.</p>
<p>So you see here, if the weight is maintained the same and the height increases, then the BMI becomes less.</p>
<p>But if the height decreases, then the BMI is high, right because of the equation of the BMI, whereby the weight is divided by the height squared, okay, and so you can play around existing values, playing around with the template.</p>
<p>So let's say you want to change the United theme to become a Boolean.</p>
<p>Save it, reload the app, and here you go, you get a different colored web application.</p>
<p>Right.</p>
<p>So the types of theme could be obtained by looking at the websites.</p>
<p>You can Google that Google for shiny themes, click on the click on the art studio.github.io slash shiny themes.</p>
<p>So I'll provide the link in the description down below.</p>
<p>So check that out.</p>
<p>In this video, I'm going to show you how you could deploy a shiny web application.</p>
<p>And without further ado, we're starting right now.</p>
<p>Okay, so the first thing that you want to do is head over to the GitHub of the data professor.</p>
<p>And you want to click on repositories, then find and click on the iris, our Heroku.</p>
<p>And so all of the files that are needed to deploy your app is found here.</p>
<p>So feel free to clone this to your own GitHub or also you could download the entire folder content here by clicking on the code and then download zip file.</p>
<p>So let's have a look here.</p>
<p>So you're gonna see that we have the UI dot r, which is the user interface.</p>
<p>And we also have server dot r, which is the server side component of the web app.</p>
<p>So essentially, the our shiny web app will be comprised of two components, the user interface and the server component.</p>
<p>And then we're going to have the training data set and the testing data set as the CSV file.</p>
<p>And the actual model will be contained within the model dot RDS.</p>
<p>And so the machine learning model is saved as the model dot RDS.</p>
<p>And it will be loaded into the web application when we run it.</p>
<p>And then there are two additional r files.</p>
<p>Let's have a look.</p>
<p>So the first one is in that dot r.</p>
<p>And so let's have a look here.</p>
<p>So it will allow us to install the necessary libraries.</p>
<p>So we're going to install the random forest and the data dot table.</p>
<p>And the run dot r will allow us to run the R shiny and assign the proper ports.</p>
<p>Okay.</p>
<p>And so that's all there is to having the necessary components for deploying your our shiny web application.</p>
<p>So let's head over to Hiroko.</p>
<p>And so you want to click on new create new app.</p>
<p>And then you want to give the app a name.</p>
<p>So let me call it VP, Iris, our create app.</p>
<p>And then I want to connect to GitHub.</p>
<p>And I'll find Iris or he Roku.</p>
<p>So for your case, you want to find your own GitHub and you want to find your own RSR he Roku and then connect.</p>
<p>And then this is very important, because you want to click on settings.</p>
<p>And in order to have the support for our, you're going to need to add the custom build pack.</p>
<p>And so you want to click on the Add build pack.</p>
<p>And you're going to notice that there are some officially supported build packs.</p>
<p>So by default, you're going to have Python, right, and you're going to have others like PHP, Ruby, Java, node j s.</p>
<p>And so for our we're going to use a third party.</p>
<p>And the third party link to the build pack for R is given here.</p>
<p>So I'm going to provide you this link in the description of this video.</p>
<p>So you want to copy that and then put it here as well.</p>
<p>And then click on save changes.</p>
<p>And then you're going to see that it has been added successfully here.</p>
<p>Now you want to head back to deploy, scroll down and you want to click on deploy branch in the manual deploy.</p>
<p>So at this point, you want to take a break, grab a cup of coffee and wait for the web app to deploy.</p>
<p>So we're gonna see the log of what is happening here.</p>
<p>So initially, it is installing version 3.6, point three here.</p>
<p>And it is downloading the bill pack directly from Amazon Web Service, and also having shiny as well.</p>
<p>Right, so it's installing the data dot table library.</p>
<p>And right now it's building the environment.</p>
<p>So this web application has already been built in a previous video.</p>
<p>So the link to that video will be provided in the description down below.</p>
<p>And in the meantime, maybe I could show you that shiny and it is number four Iris predictor.</p>
<p>And so you're going to notice that we've been using the testing and training and for the app, we divided the components of UI and server into these separate files.</p>
<p>Okay, and so it's compressing the environment from 499 megabytes to 121 megabytes.</p>
<p>Although the our packages occupies 121 megabytes, okay, so it has compressed it down to 152.</p>
<p>And it is deploying the web application to dp that's Iris dash r dot e Roku app.com.</p>
<p>And so in just a moment, you're going to see a link to view the deployed websites.</p>
<p>Okay, finished.</p>
<p>And so it says that your app was successfully deployed.</p>
<p>Let's click on it.</p>
<p>Alright, so it says here that server is ready for a calculation.</p>
<p>Let's submit All right, so predictions seems to work and it is predicted to be setosa with the probability of 100%.</p>
<p>k this predicted to be pseudoscience.</p>
<p>Well, same thing she told us and now it was predicted to be virginica.</p>
<p>100% virginica.</p>
<p>Thank you for watching until the end of this video, and I hope that this video was helpful to you.</p>
<p>And for more tutorials in data science, Bioinformatics, as well as Python and our coding tutorials, please check out my YouTube channel at the data professor and also my new and second YouTube channel decoding professor.</p>
<p>And you can also find me on the medium platform where I blog about data science as well as doing Python tutorials.</p>
<p>And last but not least, I would like to thank Free Code Camp for this awesome collaboration.</p>
<p>And please don't forget to smash the like button, subscribe if you haven't already.</p>
<p>And until next time, the best way to learn data science is to do data science, and please enjoy the journey.   </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An introduction to aggregates in R: a powerful tool for playing with data ]]>
                </title>
                <description>
                    <![CDATA[ By Satyam Singh Chauhan Data Visualization is not just about colors and graphs. It’s about exploring the data and visualizing the right thing. _[Source](https://newatlas.com/art-ones-and-zeros-data-visualization/49926/" rel="noopener" target="blank"... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/aggregates-in-r-one-of-the-most-powerful-tool-you-can-ask-for-4dd14eafff1f/</link>
                <guid isPermaLink="false">66c34399da6800e8bc5ea677</guid>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ statistics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 12 Mar 2019 05:56:18 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*qrUMlOEP2g1rEyYIqsGmag.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Satyam Singh Chauhan</p>
<p>Data Visualization is not just about colors and graphs. It’s about exploring the data and visualizing the right thing.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Ug0gL20sBjocoXthSSPx043hLj8MBO82d2J4" alt="Image" width="616" height="347" loading="lazy">
_[Source](https://newatlas.com/art-ones-and-zeros-data-visualization/49926/" rel="noopener" target="<em>blank" title=")</em></p>
<p>While playing with the data, the most powerful tool that comes handy is Aggregates. Aggregates is just the type of transformation that we apply to any given data.</p>
<h4 id="heading-we-have-11-aggregate-function-available-to-us">We have 11 aggregate function available to us:</h4>
<ul>
<li><strong>avg</strong><br>Average of all numeric values is calculated and returned.</li>
<li><strong>count</strong><br>Function count returns total number of items in each group.</li>
<li><strong>first</strong><br>The first value of each group is returned by the function first.</li>
<li><strong>last</strong><br>The last value of each group is returned by the function last.</li>
<li><strong>max</strong><br>The max value of each group is returned by the function max.<br>It is very helpful to identify outliers as well.</li>
<li><strong>median</strong><br>The median of all numeric values for the mentioned group is returned by the function median.</li>
<li><strong>min</strong><br>The min value of each group is returned by the function min.<br>It is very helpful to identify outliers as well.</li>
<li><strong>mode</strong><br>The mode of all numeric values for the mentioned group is returned by the function mode.</li>
<li><strong>rms</strong><br>Root Mean Square, rms value for all numeric values in the group is returned by the fucntion rms.</li>
<li><strong>sttdev</strong><br>Standard Deviation of all Numeric values given in the group is returned by the function stddev.</li>
<li><strong>sum</strong><br>Sum of all the numeric values is returned by the function sum.</li>
</ul>
<h3 id="heading-basic-examples">Basic Examples</h3>
<h4 id="heading-basic-visual-scatter-plot-using-aggregate-function-sum"><strong>Basic Visual Scatter plot using aggregate function — sum</strong></h4>
<pre><code>#Include the Librarylibrary(plotly)
</code></pre><pre><code>#Store the graph <span class="hljs-keyword">in</span> one variable to make it easier to manipulate.p &lt;- plot_ly(     type = <span class="hljs-string">'scatter'</span>,     y = iris$Petal.Length/iris$Petal.Width,     x = iris$Species,     mode = <span class="hljs-string">'markers'</span>,     marker = list(          size = <span class="hljs-number">15</span>,          color = <span class="hljs-string">'green'</span>,          opacity = <span class="hljs-number">0.8</span>     ),     transforms = list(          list(               type = <span class="hljs-string">'aggregate'</span>,               groups = iris$Species,               aggregations = list(                    list(                         target = <span class="hljs-string">'y'</span>, func = <span class="hljs-string">'sum'</span>, enabled = T                    )               )          )     ))
</code></pre><pre><code>#Display the graphp
</code></pre><h4 id="heading-what-does-this-mean"><strong>What does this mean?</strong></h4>
<p>Function sum, as mentioned above, calculates the sum of each group.<br>Thus, here the groups are categorized as species. This code uses the Iris Data Set which consist three different species, setosa, veriscolor, and virginica. For each species there are 50 observations in the data set. This data set is available in R (built-in) and can be loaded directly.</p>
<p>There are “iris” and “iris3” - two data sets are available. You can choose any one of them to run this code. The Data-Set used in this article is “iris”.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/EnWQv4TE1ef5oBEtsEfwHy3bWYgs1R-6pfCi" alt="Image" width="700" height="450" loading="lazy">
<em><strong>Fig. 1 Sum</strong> of Petal Length</em></p>
<h4 id="heading-what-does-this-code-do-exactly"><strong>What does this code do</strong> exactly<strong>?</strong></h4>
<p>This code uses the function sum and calculates the <strong>sum of all the Petal.Length</strong> of each group respectively. Then, the calculated sum is plotted on the x-y axis. Where the x-axis is Species, the y-axis shows the Summation.</p>
<p>From this graph, we can get an idea that the petal size of setosa is smallest as the sum is the smallest, but <strong>it’s not conclusive evidence</strong>. To get conclusive evidence we can use the function avg.</p>
<p>The function sum is <strong>very suitable for almost the whole data set</strong>. For example, one of the best places where this can be used is in Population Data Set. In the world population data set, we can aggregate countries according to continents and find the sum of all the population of the countries in it.</p>
<h4 id="heading-most-used-function-avg"><strong>Most used function — avg</strong></h4>
<pre><code>#Include the Librarylibrary(plotly)
</code></pre><pre><code>#Store the graph <span class="hljs-keyword">in</span> one variable to make it easier to manipulate.q &lt;- plot_ly(     type = <span class="hljs-string">'bar'</span>,     y = iris$Petal.Length/iris$Petal.Width,     x = iris$Species,     color = iris$Species,     transforms = list(          list(               type = <span class="hljs-string">'aggregate'</span>,               groups = iris$Species,               aggregations = list(                    list(                         target = <span class="hljs-string">'y'</span>, func = <span class="hljs-string">'avg'</span>, enabled = T                    )               )          )     ))
</code></pre><pre><code>#Display the graphq
</code></pre><h4 id="heading-what-does-this-mean-1"><strong>What does this mean?</strong></h4>
<p>The iris data-set contains two columns for Petals, Petal.Width and Petal.Length. Further, it can be used to calculate the average of the ratio of Petal.Length &amp; Petal.Width.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/WquPjhqcCIQMdipWdmZz-RkbGk6hyx3BxtnN" alt="Image" width="700" height="450" loading="lazy">
<em><strong>Fig. 2</strong> <strong>Average</strong> ratio of Petal Length to Petal Width</em></p>
<h4 id="heading-what-does-this-code-do-exactly-1"><strong>What does this code do exactly?</strong></h4>
<p>For each observation, the ratio of Petal.Length to Petal.Width is calculated before the average of all the gained values is plotted. As we can observe from this Bar Plot, Setosa has the max ratio with a near-ratio of 7, which shows that the petal length in Setosa is 7 times longer than its width. While on the other hand, virginica has the smallest ratio with nearly 3 times the width.</p>
<p>This function is very flexible and especially when it’s used very wisely to get the best result. For example, if we consider some other data-set like Population, then we can calculate the average birth to death ratio for each country.</p>
<p>Let’s use all the functions in one graph. Now we’re going to plot a scatter plot for each category and we’re going to use all the functions. To this graph we will add a button from which we can select the desired function to make our work easier and get the results quicker.</p>
<h4 id="heading-aggregation-of-all-functions-all-functions-in-one-graph"><strong>Aggregation of all functions — all functions in one-graph</strong></h4>
<pre><code>#Include the Librarylibrary(plotly)
</code></pre><pre><code>#Store the graph <span class="hljs-keyword">in</span> one variable to make it easier to manipulate.s &lt;- schema()agg &lt;- s$transforms$aggregate$attributes$aggregations$items$aggregation$func$valuesl = list()
</code></pre><pre><code><span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:length(agg)) {     ll = list(method = <span class="hljs-string">"restyle"</span>,     args = list(<span class="hljs-string">'transforms[0].aggregations[0].func'</span>, agg[i]),     label = agg[i])     l[[i]] = ll     }
</code></pre><pre><code>p &lt;- plot_ly(     type = <span class="hljs-string">'scatter'</span>,     x = iris$Species,     y = iris$Sepal.Length / iris$Sepal.Width,     mode = <span class="hljs-string">'markers'</span>,     marker = list(          size = <span class="hljs-number">20</span>,          color = <span class="hljs-string">'orange'</span>,          opacity = <span class="hljs-number">0.8</span>          ),     transforms = list(          list(               type = <span class="hljs-string">'aggregate'</span>,               groups = iris$Species,               aggregations = list(                    list(                         target = <span class="hljs-string">'y'</span>, func = <span class="hljs-string">'avg'</span>, enabled = T                    )               )            )     )) %&gt;%layout(     title = <span class="hljs-string">'&lt;b&gt;Plotly Aggregations by Satyam Chauhan&lt;/b&gt;&lt;br&gt;use     dropdown to change aggregation&lt;br&gt;&lt;b&gt;Sepal ratio of Length to     Width&lt;/b&gt;'</span>,     xaxis = list(title = <span class="hljs-string">'Species'</span>),     yaxis = list(title = <span class="hljs-string">'Sepal ratio: Length/Width'</span>),     updatemenus = list(          list(               x = <span class="hljs-number">0.2</span>,               y = <span class="hljs-number">1.2</span>,               xref = <span class="hljs-string">'paper'</span>,               yref = <span class="hljs-string">'paper'</span>,               yanchor = <span class="hljs-string">'top'</span>,               buttons = l          )     ))
</code></pre><pre><code>#Display the graphs
</code></pre><h4 id="heading-what-does-this-mean-2"><strong>What does this mean?</strong></h4>
<p>We make a list where all the function attributes of aggregation are stored. We use this function to experiment with all the functions of Aggregations in R.</p>
<p>A few of the graphs with different examples are shown below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LAZGT3Xc5MoFJxY2aGAuMzUoFrApOv8fQpr-" alt="Image" width="800" height="347" loading="lazy">
<em><strong>Fig. 3</strong> Illustrates the function <strong>mode</strong>.</em></p>
<h4 id="heading-what-does-this-code-do-exactly-2"><strong>What does this code do exactly?</strong></h4>
<p>First, a list is created as mentioned earlier, in which all the functions are stored. After the list is made, the y-axis is set to the ratio of Sepal.Length to Sepal.Width and x-axis is set to Species.</p>
<p>After calculating the ratio, the function transform is called in which the func = ‘avg’ is mentioned for just the starting phase. When we run this code and select the function ‘mode’, we get <strong>Fig. 3 (above),</strong> which shows that the mode of setosa is the least among the three at around 1.4. Mode tells that the ratio 1.4 is repeated the most times or that value is most likely to be sampled. The different pattern we saw here is that the highest value most likely to be sampled is from the category veriscolor having a mode near to 2.2.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/blyoNGdXEKhCmxlAX0zvwQWb8qqcnY7TkT4p" alt="Image" width="800" height="360" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/SWPbuF4i7CbgK3Sjyy-bjV01I3OFNEQvldEE" alt="Image" width="800" height="369" loading="lazy">
<em><strong>Fig. 4</strong> <strong>Left Figure</strong>: Illustrates the change in Sepal ratio of Length to Width <strong>Right Figure</strong>: Illustrates the root mean square (<strong>rms</strong>) value of the Graph</em></p>
<p>In Fig. 4 above, the change of ratio of Sepal Length to Sepal Width is plotted and we get very different results compared to the rest of the graphs. We observe the change of Setosa and Virginica to be the same and positive, while in the change of ratio by species, veriscolor is almost negative and is three times the change of the setosa and virginica.</p>
<p>On the other hand, the right figure shows the rms values of each species. We can easily see that the species veriscolor and virginica have almost same value which is significantly greater than the rms value of setosa.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Aggregation functions are one of the most powerful tools developers can ask for. They can provide you the patterns and results that you wouldn’t expect. To analyse the data visually, you have to play with the data, and to do that we need to manipulate and transform it. Aggregation functions do that for you, and they’re one of the most widely used functions in <a target="_blank" href="https://plot.ly/r/#transforms">transform</a>. This article is just a start. You can certainly explore more and apply more. That’s what explorers do.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to avoid scope creep, and other software design lessons learned the hard way ]]>
                </title>
                <description>
                    <![CDATA[ By Dror Berel From a data-science perspective. You’ve got a fresh new project on your desk, some exciting data, a challenging Kaggle competition, a new client you wish to impress, and you are fully motivated. At first, the problem seems to be well de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/scope-creep-and-other-software-design-lessons-learned-the-hard-way-edacf021965b/</link>
                <guid isPermaLink="false">66c35e4839357f9446976628</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 15 Feb 2019 20:39:55 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*eCxahff5OQ7CKpZRkcSjjA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dror Berel</p>
<h4 id="heading-from-a-data-science-perspective">From a data-science perspective.</h4>
<p>You’ve got a fresh new project on your desk, some exciting data, a challenging Kaggle competition, a new client you wish to impress, and you are fully motivated. At first, the problem seems to be well defined, and you even feel comfortable with the task in hand. You have just completed a similar task. This new one should not be much different. Maybe even just a few copy/pastes with some modifications at the edges.</p>
<p>But then it comes… The client / collaborator / boss has just one simple additional request… It usually goes like this:</p>
<blockquote>
<p>‘Hmmmm, I wonder how would the results look like if instead of x, we do only a minor change, just do y, or… you know what, let’s try both and see how it affects the results’.</p>
</blockquote>
<p>Can the initial tool/solution you chose handle such an adjustment? It may be easy to copy/paste it with a couple of alterations, but what if you have to do it again and again? For how long are you going to stick to your initial plan?</p>
<p>Within the context of machine learning, some examples are:</p>
<p><strong>Tuning</strong> ‘<em>let’s see how a different model parameter affects it’</em></p>
<p><strong>Benchmarking</strong> ‘<em>let’s see how various models affect it’</em></p>
<p><strong>Ensemble</strong> ‘<em>let’s try combining the best models together</em>’</p>
<p><strong>Resampling / cross-validation</strong> ‘<em>we must inspect for over-fitting</em>’</p>
<p>Imagine adding on top of that some complex, messy, multi-layer, high-throughput genomics data that can easily go into a very <strong>fine resolution level</strong> (gene expression / mutation / sequence, …),… AND THEN adding multiple layers of various <strong>multi-genomic</strong> data on top of each other, …AND THEN doing it for multiple cohorts / studies in a <strong>meta-analysis</strong> level … you may end up with a VERY … BIG … UGLY … MESS!</p>
<p>Sound familiar? Unfortunately, I have been in this situation more than once. As much as I was motivated to please my collaborators, at those times, my tools were…limited, and not sufficient to deliver the broader scope resolution. At that time, I might have not even been aware that a higher level of scope was relevant.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/O48mZK5UkKo3yaedlzbTagK2REVTXlwimqps" alt="Image" width="706" height="872" loading="lazy">
_[https://leankit.com/wp-content/uploads/2013/11/Screen-Shot-2013-11-25-at-4.25.52-PM.png](https://leankit.com/wp-content/uploads/2013/11/Screen-Shot-2013-11-25-at-4.25.52-PM.png" rel="noopener" target="<em>blank" title=")</em></p>
<p>A lot has been written about <a target="_blank" href="https://en.wikipedia.org/wiki/Scope_creep">scope creep</a> in the context of project management. But what would a scientist, who was mostly trained to care about the rightness of the analysis / tools, rather than the ‘management’ of the whole project, have to say about it?</p>
<p>The good news, my friend, is that it is never too late to learn from someone else’s mistakes. Here are couple of lessons, learned the hard way. (No worries, this is not another blog post about reproducible research).</p>
<h4 id="heading-lesson-1-begin-at-the-end-define-what-your-scope-is-do-you-need-to-extend-it"><strong>Lesson #1: Begin at the end! Define what your scope is. Do you need to extend it?</strong></h4>
<p>Make sure you understand what is the highest expected resolution! Brainstorm what would be the craziest outcomes of your project, and then agree on reasonable expectations within your timeframe and budget.</p>
<p>Have a very detailed, clear, definition of the project scope. For example, is your solution going to handle just one data set, or more? How are you going to validate your results? There are always going to be more methods/data sets for that, but what would be just sufficient enough?</p>
<p>The tricky challenge with scope creep is that the client doesn’t really care or think in terms of “scope”. Their goal is to get a solution that solves a hypothesis, or a business need. Whether their request is within or outside scope is entirely your problem! DEAL WITH IT!</p>
<p>In the context of <strong>machine learning</strong>, back in the day, I used ad-hoc R packages that do just one multivariate model. They did the work well, but were too specific for the developers domain, and lacked the higher resolution on comparing it with other models, or aggregating other models, or lacking resample implementation. Only later did I learn to utilized machine learning meta/aggregator packages such as mlr, tidymodels (formerly caret), or SuperLearner to extend my scope. <a target="_blank" href="https://towardsdatascience.com/meta-machine-learning-packages-in-r-c3e869b53ed6">Read more about it here</a>.</p>
<h4 id="heading-lesson-2-do-not-reinvent-the-wheel-there-are-other-experts-that-know-how-to-do-it-better-than-you"><strong>Lesson #2: Do not reinvent the wheel! There are other experts that know how to do it better than you!</strong></h4>
<p>In a role where you are expected to be multidisciplinary, and new tools/methods pop daily that are accessible for everyone to use, it may be a slippery fall into a very deep rabbit hole to explore any new approach. And guess what, nobody want you to waste their time/money on that.</p>
<p>How to bet on the right tool? Ask yourself, what do the experts in that domain use? How mature is the tool they developed? Is it going to be maintained, or deprecated? They of course had their own learning curve, and over time, have perfected their tools to overcome the common pitfalls you are about to discover.</p>
<p>For me, with genomics data, it was <strong>Bioconductor</strong> <strong>Object-oriented S4</strong> classes. <a target="_blank" href="https://medium.com/@drorberel/bioconductor-s4-classes-for-high-throughput-omic-data-fd6c304d569b">Read more here</a> about why that was the best tool for my need. Sure, it wasn’t trivial to learn, but I felt comfortable betting on it when I saw how it is implemented at top academic and industry organizations. I also knew that it was not another open source resource that might die. Instead, it as a government and academia-funded project, powered by the best experts of the domain, open, and free, for all of us to use.</p>
<h4 id="heading-lesson-3-found-a-gap-be-creative-but-keep-it-simple"><strong>Lesson #3: Found a gap? Be creative, but keep it simple!</strong></h4>
<p>But what if something in the analytical pipeline is still not in place? A missing link, nowhere to be found, that would have better fit to the specific need you have, bridging the gap?</p>
<p>Here you might need to get some dirty work done, and stop depending on others to provide you the solution. Another potentially slippery scope creep rabbit hole? Maybe… if you are not careful enough!</p>
<p>How to avoid it? Very easy: <strong>Keep it Simple!</strong></p>
<p>Here is a very simple example. Suppose you have to solve an unsupervised problem. There is definitely more than one way to it. Which one to choose? Is the simplest one, suppose ‘hierarchical clustering’, just be good enough to begin with? Implement it, see how it works with the rest of your analytical components (data, scalability, reproducibility), and later on, after things have worked out well as you planned, relax that simplification into a more complex method. Do it very carefully and gradually.</p>
<p>More examples to follow next.</p>
<h4 id="heading-lesson-4-do-not-be-afraid-to-refactor"><strong>Lesson #4: Do not be afraid to refactor!</strong></h4>
<p>Tired of patching and debugging poorly cohesive and poorly-designed code that someone else, maybe even your boss, has written long time ago, before better tools became available? You ask yourself, GRRRRR, this is such an ugly workaround, why not just simply use that new approach that was designed specifically for this task? (see lesson #2).</p>
<p>Yes, it is risky to begin everything from scratch, and sometimes you may not have the resources to do it, but perhaps it is time for a reality check.</p>
<p>But what if the refactor solution will give us different results from what our collaborators are already counting on? Well, if there was indeed a past error/bug/mistake, it is better to face it and acknowledge it now, before even more damage is done. But also remember lesson #3: If you stick to simple solutions at the core, refactoring them under broader wrapping solution should assist in producing similar results.</p>
<h4 id="heading-lesson-5-go-to-lesson-1"><strong>Lesson #5: go to lesson #1.</strong></h4>
<h3 id="heading-case-studies"><strong>Case studies:</strong></h3>
<p>Here are two case studies from my own experience working with multi genomic data. (Could easily expand to other types of data, but perhaps that is a topic for a future post).</p>
<p><strong>Case Study #1: Bioc2mlr: A utility function to transform Bioconductor’s S4 omic classes into mlr’s task and CPOs.</strong></p>
<p><a target="_blank" href="https://drorberel.github.io/Bioc2mlr/">https://drorberel.github.io/Bioc2mlr/</a></p>
<p>I love using <a target="_blank" href="https://medium.com/@drorberel/bioconductor-s4-classes-for-high-throughput-omic-data-fd6c304d569b">Bioconductor data containers for genomic data</a>, but I also love <a target="_blank" href="https://towardsdatascience.com/meta-machine-learning-packages-in-r-c3e869b53ed6">machine learning meta-aggregator toolkits</a> for analysis at higher level scope. The only problem was that they were not necessarily compatible with each other.</p>
<p>The S4 object oriented had multiple dimensions (slots), tied in together in complex constraints, that were intentionally designed to meet some purpose. But the machine learning approach was designed for a simplified, flat, two-dimensional, matrix like input structure: columns for the features/variables, and rows for the subjects/observations.</p>
<p>I needed some way of breaking the S4 constrained ties, and flattening it. But unfortunately, to the best of my knowledge, I couldn’t find a way to do so. <strong>What should I have done?</strong></p>
<p>Remember lesson #3: Should I spend my time on this task? Well… yes, why not? I felt comfortable enough with both approaches, have already experienced the ins and outs, the soft bellies, and I definitely appreciated the tremendous value of both approaches separately, but also jointly. In fact, creating this adapter package, Bioc2mlr, was not too much effort to do, and if you look at the code itself, you will see relatively simple steps.</p>
<p><strong>Conclusion of case 1</strong>: When you have a couple of good tools, but they are not compatible, create a simple new adapter to link them.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/6n5Ey7kX6Pfl5lD2Vxb5H-iWIxy6HCck0-RC" alt="Image" width="800" height="450" loading="lazy">
_[https://drorberel.github.io/Bioc2mlr/](https://drorberel.github.io/Bioc2mlr/" rel="noopener" target="<em>blank" title=")</em></p>
<p><strong>Case study #2: meta analysis</strong></p>
<blockquote>
<p>But that wasn’t enough for me…(see lesson #5).</p>
</blockquote>
<p>My scope extension required me to provide a solution to even higher level of analysis. Meta-analysis of multiple studies/cohorts, each with a multi-omic data cube, each with a downstream machine learning analytics pipeline, implementing resampling, and all that jazz, across all studies, and at scale. Phewww!</p>
<blockquote>
<p>Quite a challenge! How should I address that implementing the above lessons?</p>
</blockquote>
<p>Lesson #1: I began at the end. My ‘observation-unit’, row, in a tidy-fashion is not the subject, neither is the gene, nor is just one of the omics. It is the entire study/cohort (that is, a whole data cube) well-compressed into a single object in R. More than one cohort? Not a problem at all. Add as many as rows as you need for more cohorts.</p>
<p>Lesson #2: Didn’t have to invent a new tool. The experts in our field have already figured it out for us. They might have not had this implementation in mind when they did so, but if I can do it, so can you. Just give it a try.</p>
<p>Lesson #3: I found a simple solution. Should I invent/extend a new S4 object oriented class for this type of multi-cohort, multi-omic data? Of course not. There must be a simple solution. My simple solution: a tidy / nested data structure, with non-atomic objects at each cell. <a target="_blank" href="https://medium.com/@drorberel/meta-analysis-of-multiple-multi-omic-oy-vey-a45a9533e68d">Read more about it here</a>.</p>
<p>Lesson #4: Refactor? Well. Maybe I am not there yet now, since so far my (current) scope can handle all my wildest dreams. But if you show me a better approach, perhaps a data.table one (I know), or even in python (god forbid), I would not hesitate to give it a try, even if it is beyond my comfort zone.</p>
<p>Lesson #5: Meta-meta analysis? (Not a typo). Who knows. Maybe one day.</p>
<p><strong>Conclusion of case 2</strong>: tidy everything! Even non-atomic objects.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/XY28EOvuRnyI-vargYm4Tn63tvLOV7Ep-tby" alt="Image" width="800" height="450" loading="lazy">
_[https://drorberel.github.io/aboutme](https://drorberel.github.io/aboutme" rel="noopener" target="<em>blank" title=")</em></p>
<h4 id="heading-one-last-piece-of-advice-get-an-experts-opinion-at-least-until-you-become-one-yourself"><strong>One last piece of advice: Get an expert’s opinion, at least until you become one yourself.</strong></h4>
<p>‘If only I had known that before. That could have saved me so much time and effort…’</p>
<p>To the expert, your current challenges are yesterday’s resolution. They had already figured that out when we were still in kindergarten. They have spent their entire career just on that. Shoot them an email, ask a very clear question, with no dependencies proof-of-concepts examples, or case studies to demonstrate your challenge. My experience is that they would be happy to assist if you respect their time and authority.</p>
<h3 id="heading-final-words"><strong>Final words</strong></h3>
<p>When you figure out what type of tool/solution you are passionate about, make it happen! Don’t fool yourself with excuses why it is not a good time for your new tool to be created. Just do it!</p>
<p>Don’t give up. Focus. Decide what you want to achieve. Do not be afraid to extend your scope, but do it with simple solutions! Refactor. It will be worth your time. Maybe not immediately, but in days to come. Be creative!</p>
<p>And last but not least, don’t be shy. Tell everyone about it. Share it with your community. Make the universe a better place with your solution. You may even earn an extra buck on the side. Who knows?</p>
<p>p.s.</p>
<p>This post is dedicated with love to all of my former anxious collaborators / clients / bosses. I appreciate your patience, and wish I would have known the above before. You were there to assist and support me learning these lessons the hard way, for both good and for bad. Let me make it up to you. Shoot me an email and I will redo my old work in just a few lines of code, reflecting my current level of scope.</p>
<p>Check more related topics here: <a target="_blank" href="https://drorberel.github.io/">https://drorberel.github.io/</a></p>
<h3 id="heading-consultant-currently-accepting-new-projects">Consultant: currently accepting new projects!</h3>
<p>Useful reference:</p>
<p><a target="_blank" href="https://blog.cleancoder.com/"><strong>Clean Coder Blog</strong></a><br><a target="_blank" href="https://blog.cleancoder.com/">_On the Diminished Capacity to Discuss Things Rationally_blog.cleancoder.com</a><a target="_blank" href="https://www.workamajig.com/blog/scope-creep"><strong>Scope Creep in Project Management: Definition, Causes &amp; Solutions</strong></a><br><a target="_blank" href="https://www.workamajig.com/blog/scope-creep">_When a project stretches far beyond its original vision, it is called "scope creep". Scope creep in project management…_www.workamajig.com</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to make Beautiful Ruby Plots with Galaaz ]]>
                </title>
                <description>
                    <![CDATA[ By Rodrigo Botafogo By Rodrigo Botafogo & Daniel Mossé According to Wikipedia “Ruby is a dynamic, interpreted, reflective, object-oriented, general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro “Matz” Matsum... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-make-beautiful-ruby-plots-with-galaaz-320848058857/</link>
                <guid isPermaLink="false">66c35357b919d74bc820acf7</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 26 Nov 2018 18:13:24 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*ASC-GrL_rmt2qA2iUQg70Q.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Rodrigo Botafogo</p>
<h4 id="heading-by-rodrigo-botafogo-amp-daniel-mosse">By Rodrigo Botafogo &amp; Daniel Mossé</h4>
<p>According to Wikipedia “Ruby is a dynamic, interpreted, reflective, object-oriented, general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro “Matz” Matsumoto in Japan.” It reached high popularity with the development of Ruby on Rails (RoR) by David Heinemeier Hansson.</p>
<p>RoR is a web application framework first released around 2005. It makes extensive use of Ruby’s meta-programming features. With RoR, Ruby became very popular. According to <a target="_blank" href="https://www.tiobe.com/tiobe-index/ruby/">Ruby’s Tiobe index</a> it peaked in popularity around 2008, then declined until 2015 when it started picking up again.</p>
<p>At the time of this writing (November 2018), the Tiobe index puts Ruby in 16th position as most popular language.</p>
<p>Python, a language similar to Ruby, ranks 4th in the index. Java, C and C++ take the first three positions. Ruby is often criticized for its focus on web applications. But Ruby can do <a target="_blank" href="https://github.com/markets/awesome-ruby">much more</a> than just web applications. Yet, for scientific computing, Ruby lags way behind Python and R. Python has the Django framework for web, NumPy for numerical arrays, and Pandas for data analysis. R is a free software environment for statistical computing and graphics with thousands of libraries for data analysis.</p>
<p>Until recently, there was no real way for Ruby to bridge this gap. Implementing a complete scientific computing infrastructure would take too long. Enters <a target="_blank" href="https://www.graalvm.org/">Oracle’s GraalVM</a>:</p>
<blockquote>
<p><em>GraalVM is a universal virtual machine for running applications written in JavaScript, Python 3, Ruby, R, JVM-based languages like Java, Scala, Kotlin, and LLVM-based languages such as C and C++.</em></p>
<p><em>GraalVM removes the isolation between programming languages and enables interoperability in a shared run-time. It can run either standalone or in the context of OpenJDK, Node.js, Oracle Database, or MySQL.</em></p>
<p><em>GraalVM allows you to write polyglot applications with a seamless way to pass values from one language to another. With GraalVM there is no copying or marshaling necessary as it is with other polyglot systems. This lets you achieve high performance when language boundaries are crossed. Most of the time there is no additional cost for crossing a language boundary at all.</em></p>
<p><em>Often developers have to make uncomfortable compromises that require them to rewrite their software in other languages. For example:</em></p>
<ul>
<li><p>“That library is not available in my language. I need to rewrite it.”</p>
</li>
<li><p>“That language would be the perfect fit for my problem, but we cannot run it in our environment.”</p>
</li>
<li><p>“That problem is already solved in my language, but the language is too slow.”</p>
</li>
</ul>
<p><em>With GraalVM we aim to allow developers to freely choose the right language for the task at hand without making compromises.</em></p>
</blockquote>
<p>As stated above, GraalVM is a <em>universal</em> virtual machine that allows Ruby and R (and other languages) to run on the same environment. GraalVM allows polyglot applications to <em>seamlessly</em> interact with one another and pass values from one language to the other.</p>
<p>GraalVM is a very powerful environment. Yet, it still requires application writers to know several languages. To eliminate that requirement, we built Galaaz, a gem for Ruby, to tightly couple Ruby and R and allow those languages to interact in a way that the user will be unaware of such interaction. In other words, a Ruby programmer will be able to use all the capabilities of R without knowing the R syntax.</p>
<p>Library wrapping is a usual way of bringing features from one language into another. To improve performance, Python often wraps more efficient C libraries. For the Python developer, the existence of such C libraries is hidden. The problem with library wrapping is that for any new library, there is the need to handcraft a new wrapper requiring a high level of expertise and time.</p>
<p>Galaaz, instead of wrapping a single C or R library, wraps the whole R language in Ruby. Doing so, all thousands of R libraries are available immediately to Ruby developers without any new wrapping effort.</p>
<p>To show the power of Galaaz, we show in this article how Ruby can use R’s ggplot2 library transparently bringing to Ruby the power of high quality scientific plotting. We also show that migrating from R to Ruby with Galaaz is a matter of small syntactic changes. By using Ruby, the R developer can use all of Ruby’s powerful object-oriented features. Also, with Ruby, it becomes much easier to move code from the analysis phase to the production phase.</p>
<p>In this article we will explore the R ToothGrowth dataset. To illustrate, we will create some boxplots. A primer on boxplot is available in <a target="_blank" href="https://towardsdatascience.com/understanding-boxplots-5e2df7bcbd51">this article</a>.</p>
<p>We will also create a Corporate Template ensuring that plots will have a consistent visualization. This template is built using a Ruby module. There is a way of building ggplot themes that will work the same as the Ruby module. Yet, writing a new theme requires specific knowledge on theme writing. Ruby modules are standard to the language and don’t need special knowledge.</p>
<p><a target="_blank" href="https://towardsdatascience.com/ruby-plotting-with-galaaz-an-example-of-tightly-coupling-ruby-and-r-in-graalvm-520b69e21021">Here</a> we show a scatter plot in Ruby also with Galaaz.</p>
<h3 id="heading-gknit">gKnit</h3>
<p><em>Knitr</em> is an application that converts text written in rmarkdown to many different output formats. For instance, a writer can convert an rmarkdown document to HTML, <em>LaTex</em>, docx and many other formats.</p>
<p>Rmarkdown documents can contain text and <em>code chunks</em>. Knitr formats code chunks in a grayed box in the output document. It also executes the code chunks and formats the output in a white box. Every line of output from the execution code is preceded by ‘##’.</p>
<p>Knitr allows code chunks to be in R, Python, Ruby and dozens of other languages. Yet, while R and Python chunks can share data, in other languages, chunks are independent. This means that a variable defined in one chunk cannot be used in another chunk.</p>
<p>With <em>gKnit</em> Ruby code chunks can share data. In gKnit each Ruby chunk executes in its own scope and thus, local variable defined in a chunk are not accessible by other chunks. Yet, All chunks execute in the scope of a ‘chunk’ class and instance variables (‘@’), are available in all chunks.</p>
<h3 id="heading-exploring-the-dataset">Exploring the Dataset</h3>
<p>Let’s start by exploring our selected dataset. A dataset is like a simple excel spreadsheet, in which each column has only one type of data. For instance one column can have float, the other integer, and a third strings.</p>
<p>ToothGrowth R dataset analyzes the length of odontoblasts (cells responsible for tooth growth) in 60 guinea pigs, where each animal received one of three dose levels of Vitamin C (0.5, 1, and 2 mg/day) by one of two delivery methods, orange juice (OJ) or ascorbic acid (a form of vitamin C and coded as VC).</p>
<p>The ToothGrowth dataset contains three columns: ‘len’, ‘supp’ and ‘dose’. Let’s take a look at a few rows of this dataset.</p>
<p>In Galaaz, R variables are accessed by using the corresponding Ruby symbol preceded by the tilde (‘~’) function. Note in the following chunk that ‘ToothGrowth’ is the R variable and Ruby’s ‘@tooth_growth’ is assigned the value of ‘~:ToothGrowth’.</p>
<pre><code># Read the R ToothGrowth variable and assign it to the# Ruby instance variable @tooth_growth that will be # available to all Ruby chunks <span class="hljs-keyword">in</span> <span class="hljs-built_in">this</span> <span class="hljs-built_in">document</span>.@tooth_growth = ~:ToothGrowth
</code></pre><pre><code># print the first few elements <span class="hljs-keyword">of</span> the datasetputs @tooth_growth.head
</code></pre><pre><code>##    len supp dose## <span class="hljs-number">1</span>  <span class="hljs-number">4.2</span>   VC  <span class="hljs-number">0.5</span>## <span class="hljs-number">2</span> <span class="hljs-number">11.5</span>   VC  <span class="hljs-number">0.5</span>## <span class="hljs-number">3</span>  <span class="hljs-number">7.3</span>   VC  <span class="hljs-number">0.5</span>## <span class="hljs-number">4</span>  <span class="hljs-number">5.8</span>   VC  <span class="hljs-number">0.5</span>## <span class="hljs-number">5</span>  <span class="hljs-number">6.4</span>   VC  <span class="hljs-number">0.5</span>## <span class="hljs-number">6</span> <span class="hljs-number">10.0</span>   VC  <span class="hljs-number">0.5</span>
</code></pre><p>Great! We’ve managed to read the ToothGrowth dataset and take a look at its elements. We see here the first 6 rows of the dataset. To access a column, follow the dataset name with a dot (‘.’) and the name of the column. Also use dot notation to chain methods in usual Ruby style.</p>
<pre><code># Access the tooth_growth <span class="hljs-string">'len'</span> column and print the first few# elements <span class="hljs-keyword">of</span> <span class="hljs-built_in">this</span> column <span class="hljs-keyword">with</span> the <span class="hljs-string">'head'</span> method.puts @tooth_growth.len.head
</code></pre><pre><code>## [<span class="hljs-number">1</span>]  <span class="hljs-number">4.2</span> <span class="hljs-number">11.5</span>  <span class="hljs-number">7.3</span>  <span class="hljs-number">5.8</span>  <span class="hljs-number">6.4</span> <span class="hljs-number">10.0</span>
</code></pre><p>The ‘dose’ column contains a numeric value with either, 0.5, 1 or 2, although the first 6 rows as seen above only contain the 0.5 values. Even though those are number, they are better interpreted as a <a target="_blank" href="https://swcarpentry.github.io/r-novice-inflammation/12-supp-factors/">factor or category</a>. So, let’s convert our ‘dose’ column from numeric to ‘factor’.</p>
<p>In R, the function ‘as.factor’ is used to convert data in a vector to factors. To use this function from Galaaz the dot (‘.’) in the function name is substituted by ’<strong>‘(double underline). The function ’as.factor’ becomes ’R.as</strong>factor’ or just ’as__factor’ when chaining.</p>
<pre><code># convert the dose to a factor@tooth_growth.dose = @tooth_growth.dose.as__factor
</code></pre><p>Let’s explore some more details of this dataset. In particular, let’s look at its dimensions, structure and summary statistics.</p>
<pre><code>puts @tooth_growth.dim
</code></pre><pre><code>## [<span class="hljs-number">1</span>] <span class="hljs-number">60</span>  <span class="hljs-number">3</span>
</code></pre><p>This dataset has 60 rows, one for each subject and 3 columns, as we have already seen.</p>
<p>Note that we do not need to call ‘puts’ when using the ‘str’ function. This functions does not return anything and prints the structure of the dataset as a side effect.</p>
<pre><code>@tooth_growth.str
</code></pre><pre><code>## <span class="hljs-string">'data.frame'</span>:    <span class="hljs-number">60</span> obs. of  <span class="hljs-number">3</span> variables:##  $ len : num  <span class="hljs-number">4.2</span> <span class="hljs-number">11.5</span> <span class="hljs-number">7.3</span> <span class="hljs-number">5.8</span> <span class="hljs-number">6.4</span> <span class="hljs-number">10</span> <span class="hljs-number">11.2</span> <span class="hljs-number">11.2</span> <span class="hljs-number">5.2</span> <span class="hljs-number">7</span> ...##  $ supp: Factor w/ <span class="hljs-number">2</span> levels <span class="hljs-string">"OJ"</span>,<span class="hljs-string">"VC"</span>: <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> <span class="hljs-number">2</span> ...##  $ dose: Factor w/ <span class="hljs-number">3</span> levels <span class="hljs-string">"0.5"</span>,<span class="hljs-string">"1"</span>,<span class="hljs-string">"2"</span>: <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">1</span> ...
</code></pre><p>Observe that both variables ‘supp’ and ‘dose’ are factors. The system made variable ‘supp’ a factor automatically, since it contains two strings OJ and VC.</p>
<p>Finally, using the summary method, we get the statistical summary for the dataset</p>
<pre><code>puts @tooth_growth.summary
</code></pre><pre><code>##       len        supp     dose   ##  Min.   : <span class="hljs-number">4.20</span>   OJ:<span class="hljs-number">30</span>   <span class="hljs-number">0.5</span>:<span class="hljs-number">20</span>  ##  <span class="hljs-number">1</span>st Qu.:<span class="hljs-number">13.07</span>   VC:<span class="hljs-number">30</span>   <span class="hljs-number">1</span>  :<span class="hljs-number">20</span>  ##  Median :<span class="hljs-number">19.25</span>           <span class="hljs-number">2</span>  :<span class="hljs-number">20</span>  ##  Mean   :<span class="hljs-number">18.81</span>                   ##  <span class="hljs-number">3</span>rd Qu.:<span class="hljs-number">25.27</span>                   ##  Max.   :<span class="hljs-number">33.90</span>
</code></pre><h3 id="heading-doing-the-data-analysis">Doing the Data Analysis</h3>
<h4 id="heading-quick-plot-for-seeing-the-data">Quick plot for seeing the data</h4>
<p>Let’s now create our first plot with the given data by accessing ggplot2 from Ruby. For Rubyists that have never seen or used ggplot2, here is the description of ggplot found in its home page:</p>
<blockquote>
<p>“ggplot2 is a system for declaratively creating graphics, based on <em>The Grammar of Graphics</em>. You provide the data, tell ggplot2 how to map variables to aesthetics, what graphical primitives to use, and it takes care of the details.”</p>
</blockquote>
<p>This description might be a bit cryptic and it is best to see it at work to understand it. Basically, in the <em>grammar of graphics</em> developers add layers of components such as grid, axes, data, title, subtitle and also graphical primitives such as <em>bar plot</em>, <em>box plot</em>, to form the final graphics.</p>
<p>Interested readers can look up the following articles on the grammar of graphics on medium: <a target="_blank" href="https://towardsdatascience.com/a-comprehensive-guide-to-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1f92b4ed4149">A Comprehensive Guide to the Grammar of Graphics for Effective Visualization of Multi-dimensional Data</a> and <a target="_blank" href="https://towardsdatascience.com/murdering-a-legendary-data-story-what-can-we-learn-from-a-grammar-of-graphics-ad6ca42f5e30">What are the Ingredients of a Terrible Data Story?</a></p>
<p>In order to make a plot, we use the ‘ggplot’ function to the dataset. In R, this would be written as <code>ggplot(&lt;dataset&gt;</code>, ...). Galaaz gives you the flexibility to use e<code>ither R.ggplot(&lt;datas</code>et&amp;g<code>t;, ...) or &lt;datas</code>et&gt;.ggplot(...). In the graph specification bellow, we use the second notation that looks more like Ruby. Ggplot uses the ‘aes’ method to specify x and y axes; in this case, _th_e ‘dose’ on the x axis and th<em>e</em> ‘length’ on the y axis: ‘E.aes(x: :dose, y: :len)’. To specify the type of plot add a geom to the plot. For a boxplot, the geom is R.geom_boxplot.</p>
<p>Note also that we have a call to ‘R.png’ before plotting and ’R.dev<strong>off’ after the print statement. ‘R.png’ opens a ‘png device’ for outputting the plot. If we do no pass a name to the ‘png’ function, the image gets a default name of ‘Rplot’ where  is the number of the plot. ’R.dev</strong>off’ closes the device and creates the ‘png’ file. We can then include the generated ‘png’ file in the document by adding an rmarkdown directive.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sNuNOhV1RR5yn0SHaNQcSWvhWFdvwgrlQKfv" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 1: Creating a Boxplot in png format for the ToothGrowth dataset. Dose x Length of Odontoblasts</em></p>
<p>Great! We’ve just managed to create and save our first plot in Ruby with only four lines of code. We can now easily see with this plot a clear trend: as the dose of the supplement increases, so are the length of teeth.</p>
<h4 id="heading-faceting-the-plot">Faceting the plot</h4>
<p>This first plot shows a trend, but our data has information about two different forms of delivery method, either by Orange Juice (OJ) or by Vitamin C (VC). Let’s then try to create a plot that helps us discern the effect of each delivery method.</p>
<p>This next plot is a <em>facetted</em> plot where each delivery method gets is own plot. On the left side, the plot shows the OJ delivery method. On the right side, we see the VC delivery method. To obtain this plot, we use the ‘R.facet_grid’ function that automatically creates the facets based on the delivery method factors. The parameter to the ‘facet_grid’ method is a <a target="_blank" href="https://thomasleeper.com/Rcourse/Tutorials/formulae.html"><em>formula</em></a>.</p>
<p>In Galaaz we give programmers the flexibility to use two different ways to write formulas. In the first way, the following changes from writing formulas (for example ‘x ~ y’) in R are necessary:</p>
<ul>
<li>R symbols are represented by the same Ruby symbol prefixed with the ‘+’ method. The symbol <code>x</code> in R becomes <code>+:x</code> in Ruby;</li>
<li>The ‘~’ operator in R becomes ‘=~’ in Ruby. The formula <code>x ~ y</code> in R is written as <code>+:x =~ +:y</code> in Ruby;</li>
<li>The ‘.’ symbol in R becomes ‘+:all’</li>
</ul>
<p>Another way of writing a formula is to use the ‘formula’ function with the actual formula as a string. The formula <code>x ~ y</code> in R can be written as <code>R.formula("x ~ y")</code>. For more complex formulas, the use of the ‘formula’ function is preferred.</p>
<p>The formula <code>+:all =~ +:supp</code> indicates to the ‘facet_grid’ function that it needs to facet the plot based on the <code>supp</code> variable and split the plot vertically. Changing the formula to <code>+:supp =~ +:all</code> would split the plot horizontally.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facet_by_delivery.png"</span>)@base_tooth = @tooth_growth.ggplot(E.aes(x: :dose, <span class="hljs-attr">y</span>: :len, <span class="hljs-attr">group</span>: :dose))@bp = @base_tooth + R.geom_boxplot +      # Split <span class="hljs-keyword">in</span> vertical direction      R.facet_grid(+:all =~ +:supp)      puts @bpR.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/J92qK3nYjw3EMMaAnk6LglJtP87UOwTfyOOI" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 2: ToothGrowth dataset faceted by delivery method</em></p>
<p>It now becomes clear that although both methods of delivery have a direct impact on tooth growth, method OJ is non-linear having a higher impact with smaller doses of ascorbic acid and reducing it’s impact as the dose increases. With the VC approach, the impact seems to be more linear.</p>
<h4 id="heading-adding-color">Adding Color</h4>
<p>If we were writing about data analysis, we would make a better analysis of the trends and improve the statistical analysis. But here we are interested in working with ggplot in Ruby. So, let’s add some colors to this plot to make the trend and comparison more visible.</p>
<p>In the following plot, the boxes are color coded by dose. To add color, it is enough to add <code>fill: :dose</code> to the aesthetic of boxplot. With this command each ‘dose’ factor gets its own color.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facets_by_delivery_color.png"</span>)
</code></pre><pre><code>@bp = @bp + R.geom_boxplot(E.aes(fill: :dose))puts @bp
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/034ug1ms7EAZdUntbXBXdTGsq8IkhL9FIxAm" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 3: Adding color to the faceted boxplot figure</em></p>
<p>Faceting helps us compare the general trends for each delivery method. Adding color allow us to compare specifically how each dosage impacts the tooth growth. It is possible to observe that with smaller doses, up to 1mg, OJ performs better than VC (red color). For 2mg, both OJ and VC have the same median, but OJ is less disperse (blue color). For 1mg (green color), OJ is significantly better than VC. By this very quick visual analysis, it seems that OJ is a better delivery method than VC.</p>
<h3 id="heading-clarifying-the-data">Clarifying the data</h3>
<p>Boxplots give us a nice idea of the distribution of data, but looking at those plots with large colored boxes leaves us wondering what else is going on. According to Edward Tufte in Envisioning Information:</p>
<blockquote>
<p>Thin data rightly prompts suspicions: “What are they leaving out? Is that really everything they know? What are they hiding? Is that all they did?” Now and then it is claimed that vacant space is “friendly” (anthropomorphizing an inherently murky idea) but <em>it is not how much empty space there is, but rather how it is used. It is not how much information there is, but rather how effectively it is arranged.</em></p>
</blockquote>
<p>And he states:</p>
<blockquote>
<p>A most unconventional design strategy is revealed: <em>to clarify, add detail.</em></p>
</blockquote>
<p>Let’s use this wisdom and add yet another layer of data to our plot, so that we clarify it with detail and do not leave large empty boxes. In this next plot, we add data points for each of the 60 pigs in the experiment. For that, add the function ‘R.geom_point’ to the plot.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facets_with_points.png"</span>)
</code></pre><pre><code># Add point <span class="hljs-keyword">for</span> each subject@bp = @bp + R.geom_point
</code></pre><pre><code>puts @bp
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/lGlHns6Air0ndnx9e6RKAmTctSE1Anp3ahXs" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 4: Adding points for all data — Not everything can be seen because of data hiding (some points on<br>top of others)</em></p>
<p>Now we can see the actual distribution of all the 60 subjects. Actually, this is not totally true. We have a hard time seeing all 60 subjects. It seems that some points might be placed one over the other hiding useful information.</p>
<p>But no sweat! Another layer might solve the problem. In the following plot a new layer called ‘geom_jitter’ is added to the plot. Jitter adds a small amount of random variation to the location of each point, and is a useful way of handling overplotting caused by discreteness in smaller datasets. This makes it easier to see all of the points and prevents data hiding. We also add color and change the shape of the points, making them even easier to see.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facets_with_jitter.png"</span>)
</code></pre><pre><code># Use small diamonds <span class="hljs-keyword">in</span> a light blue color (cyan3) # to plot the subjects <span class="hljs-keyword">of</span> the experimentputs @bp + R.geom_jitter(shape: <span class="hljs-number">23</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"cyan3"</span>, <span class="hljs-attr">size</span>: <span class="hljs-number">1</span>)
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/VAeNnX-ZZBir2MdNZAFq8As6UIMgTNcWmdK5" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 5: Jittering the points to show those on top of each other — All data is now visible</em></p>
<h3 id="heading-preparing-the-plot-for-presentation">Preparing the Plot for Presentation</h3>
<p>We have come a long way since our first plot. As we’ve already said, this is not an article about data analysis and the focus is on the integration of Ruby and ggplot. So, let’s assume that the analysis is now done. Yet, ending the analysis does not mean that the work is done. On the contrary, the hardest part is yet to come!</p>
<p>After the analysis it is necessary to communicate it by making a final plot for presentation. The last plot has all the information we want to share, but it is not very pleasing to the eye.</p>
<h4 id="heading-improving-colors">Improving Colors</h4>
<p>Let’s start by trying to improve colors. For now, we will not use the jitter layer. The previous plot uses three bright colors. Is there any obvious, or non-obvious for that matter, interpretation for the colors? Clearly, they are just random colors selected automatically by our software. Although those colors helped us understand the data, for a final presentation random colors can distract the viewer.</p>
<p>In the following plot we use ‘scale_fill_manual’ function to change the colors of the boxes and order of labels. For colors, we use shades of blue for each dosage, with light blue (‘cyan’) representing the lower dose and deep blue (‘deepskyblue4’) the higher dose.</p>
<p>Also, the legend could be improved: we use the ‘breaks’ parameter to put the smaller value (0.5) at the bottom of the labels and the largest (2) at the top. This ordering seems more natural and matches with the actual order of the colors in the plot.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facets_by_delivery_color2.png"</span>)
</code></pre><pre><code>@bp = @bp +      R.scale_fill_manual(values: R.c(<span class="hljs-string">"cyan"</span>, <span class="hljs-string">"deepskyblue"</span>,                                      <span class="hljs-string">"deepskyblue4"</span>),                          <span class="hljs-attr">breaks</span>: R.c(<span class="hljs-string">"2"</span>,<span class="hljs-string">"1"</span>,<span class="hljs-string">"0.5"</span>))
</code></pre><pre><code>puts @bp
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/UMjgE8fRb1XtWg3Ha9YHu4k3JajqcjMTFssv" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 6: Shades of blue representing lower to higher doses</em></p>
<h4 id="heading-violin-plot-and-jitter">Violin Plot and Jitter</h4>
<p>The boxplot with jitter did look a bit overwhelming. The next plot uses a variation of a boxplot known as a <em>violin plot</em> with jittered data.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Violin_plot">From Wikipedia</a></p>
<blockquote>
<p><em>A violin plot is a method of plotting numeric data. It is similar to a box plot with a rotated kernel density plot on each side.</em></p>
<p><em>A violin plot has four layers. The outer shape represents all possible results, with thickness indicating how common. (Thus the thickest section represents the mode average.) The next layer inside represents the values that occur 95% of the time. The next layer (if it exists) inside represents the values that occur 50% of the time. The central dot represents the median average value.</em></p>
</blockquote>
<pre><code>R.png(<span class="hljs-string">"figures/violin_with_jitter.png"</span>)@violin = @base_tooth + R.geom_violin(E.aes(fill: :dose)) +    R.facet_grid(+:all =~ +:supp) +   R.geom_jitter(shape: <span class="hljs-number">23</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"cyan3"</span>, <span class="hljs-attr">size</span>: <span class="hljs-number">1</span>) +   R.scale_fill_manual(values: R.c(<span class="hljs-string">"cyan"</span>, <span class="hljs-string">"deepskyblue"</span>,                                   <span class="hljs-string">"deepskyblue4"</span>),                       <span class="hljs-attr">breaks</span>: R.c(<span class="hljs-string">"2"</span>,<span class="hljs-string">"1"</span>,<span class="hljs-string">"0.5"</span>))puts @violinR.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/fAqeGBqPTiT930llEU-xpGz53qxRRlb32p9P" alt="Image" width="480" height="480" loading="lazy">
<em>Figure 7: Violin plot with shades of blue and jitter</em></p>
<p>This plot is an alternative to the original boxplot. For the final presentation, it is important to think which graphics will be best understood by our audience. A violin plot is a less known plot and could add mental overhead, yet, in my opinion, it does look a bit better than the boxplot and provides even more information than the boxplot with jitter.</p>
<h4 id="heading-adding-decoration">Adding Decoration</h4>
<p>Our final plot is starting to take shape, but a presentation plot should have at least a title, labels on the axes and maybe some other decorations. Let’s start adding those. Since decoration requires more graph area, this new plot has a ‘width’ and ‘height’ specification. When there is no specification, the default values from R for width and height are 480 pixels.</p>
<p>The ‘labs’ function adds the required decoration. In this example we use ‘title’, ‘subtitle’, ‘x’ for the <em>x</em> axis label and ‘y’, for the <em>y</em> axis label, and ‘caption’ for information about the plot (for clarity, we defined a caption variable using Ruby’s Here Doc style).</p>
<pre><code>R.png(<span class="hljs-string">"figures/facets_with_decorations.png"</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">540</span>,       <span class="hljs-attr">height</span>: <span class="hljs-number">560</span>)
</code></pre><pre><code>caption = &lt;&lt;-EOTLength <span class="hljs-keyword">of</span> odontoblasts <span class="hljs-keyword">in</span> <span class="hljs-number">60</span> guinea pigs. Each animal received one <span class="hljs-keyword">of</span> three dose levels <span class="hljs-keyword">of</span> vitamin C.EOT
</code></pre><pre><code>@decorations =  R.labs(title: <span class="hljs-string">"Tooth Growth:  Length vs Vitamin C Dose"</span>,         <span class="hljs-attr">subtitle</span>: <span class="hljs-string">"Faceted by delivery method, OJ or VC"</span>,         <span class="hljs-attr">x</span>: <span class="hljs-string">"Dose (mg)"</span>, <span class="hljs-attr">y</span>: <span class="hljs-string">"Teeth length"</span>,         <span class="hljs-attr">caption</span>: caption)
</code></pre><pre><code>puts @bp + @decorations
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/DpMjSWKd2xkw75DJnV8-GtfSkRg0MWSG9LUT" alt="Image" width="540" height="560" loading="lazy">
<em>Figure 8: Adding title, subtitle, axes names and caption</em></p>
<h4 id="heading-the-corp-theme">The Corp Theme</h4>
<p>We are almost done. But the default plot configuration does not yet look nice to the eye. We are still distracted by many aspects of the graph. First, the black font color does not look good. Then plot background, borders, grids all add clutter to the plot.</p>
<p>We will now define our corporate theme. in a module that can be used/loaded for all plots, similar to CSS or any other style definition.</p>
<p>In this theme, we remove borders and grids. The background is left for faceted plots but removed for non-faceted plots. Font colors are a shade o blue (color: ‘#00080’). Axes labels are moved near the end of the axis and written in ‘bold’.</p>
<pre><code><span class="hljs-built_in">module</span> CorpTheme
</code></pre><pre><code>R.install_and_loads <span class="hljs-string">'RColorBrewer'</span>   #----------------------------------------------------------------# face can be  (<span class="hljs-number">1</span>=plain, <span class="hljs-number">2</span>=bold, <span class="hljs-number">3</span>=italic, <span class="hljs-number">4</span>=bold-italic)#----------------------------------------------------------------    def self.text_element(size, <span class="hljs-attr">face</span>: <span class="hljs-string">"plain"</span>, <span class="hljs-attr">hjust</span>: nil)    E.element_text(color: <span class="hljs-string">"#000080"</span>,                    <span class="hljs-attr">face</span>: face,                   <span class="hljs-attr">size</span>: size,           <span class="hljs-attr">hjust</span>: hjust)  end  #----------------------------------------------------------------# Defines the plot theme (visualization).  In <span class="hljs-built_in">this</span> theme we # remove major and minor grids, borders and background.  We # also turn-off scientific notation.#----------------------------------------------------------------    def self.global_theme(faceted = <span class="hljs-literal">false</span>)    # turn-off scientific notation like <span class="hljs-number">1e+48</span>    R.options(scipen: <span class="hljs-number">999</span>)    # remove major grids    gb = R.theme(panel__grid__major: E.element_blank())    # remove minor grids    gb = gb + R.theme(panel__grid__minor: E.element_blank)    # remove border    gb = gb + R.theme(panel__border: E.element_blank)    # remove background. When working <span class="hljs-keyword">with</span> faceted graphs,     # the background makes it easier to see each facet, so     # leave it    gb = gb +       R.theme(panel__background: E.element_blank) <span class="hljs-keyword">if</span> !faceted    # Change axis font    gb = gb + R.theme(axis__text: text_element(<span class="hljs-number">8</span>))    # change axis title font    gb = gb +      R.theme(axis__title:        text_element(<span class="hljs-number">10</span>, <span class="hljs-attr">face</span>: <span class="hljs-string">"bold"</span>, <span class="hljs-attr">hjust</span>: <span class="hljs-number">1</span>))    # change font <span class="hljs-keyword">of</span> title    gb = gb + R.theme(title: text_element(<span class="hljs-number">12</span>, <span class="hljs-attr">face</span>: <span class="hljs-string">"bold"</span>))    # change font <span class="hljs-keyword">of</span> subtitle    gb = gb + R.theme(plot__subtitle: text_element(<span class="hljs-number">9</span>))    # change font <span class="hljs-keyword">of</span> captions    gb = gb + R.theme(plot__caption: text_element(<span class="hljs-number">8</span>))
</code></pre><pre><code>  end   end
</code></pre><h3 id="heading-final-box-plot">Final Box Plot</h3>
<p>We can now easily make our final boxplot and violin plot. All the layers for the plot were added in order to expose our understanding of the data and the need to present the result to our audience.</p>
<p>The final specification is just the addition of all layers build up to this point (@bp), plus the decorations (@decorations), plus the corporate theme.</p>
<p>Here is our final boxplot, without jitter.</p>
<pre><code>R.png(<span class="hljs-string">"figures/final_box_plot.png"</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">560</span>)
</code></pre><pre><code>puts @bp + @decorations + CorpTheme.global_theme(faceted: <span class="hljs-literal">true</span>)
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/uEF8SYydBXvhWNZ0dxSdZgo-zmGf6hdk6wur" alt="Image" width="540" height="560" loading="lazy">
<em>Figure 9: Final boxplot with all decoration, but no jitter</em></p>
<p>And here is the final violin plot, with jitter and the same look and feel of the corporate boxplot.</p>
<pre><code>R.png(<span class="hljs-string">"figures/final_violin_plot.png"</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">560</span>)
</code></pre><pre><code>puts @violin + @decorations + CorpTheme.global_theme(faceted: <span class="hljs-literal">true</span>)
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/MX06B6ui335Y9JleNaGXWp0r67CiiB-uz-Wu" alt="Image" width="540" height="560" loading="lazy">
<em>Figure 10: Final violin plot, with decorations and jitter</em></p>
<h3 id="heading-another-view">Another View</h3>
<p>We now make another plot, with the same look and feel as before but facetted by dose and not by supplement. This shows how easy it is to create new plots by just changing small statement on the <em>grammar of graphics</em>.</p>
<pre><code>R.png(<span class="hljs-string">"figures/facet_by_dose.png"</span>, <span class="hljs-attr">width</span>: <span class="hljs-number">540</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">560</span>)
</code></pre><pre><code>caption = &lt;&lt;-EOTLength <span class="hljs-keyword">of</span> odontoblasts <span class="hljs-keyword">in</span> <span class="hljs-number">60</span> guinea pigs. Each animal received one <span class="hljs-keyword">of</span> three dose levels <span class="hljs-keyword">of</span> vitamin C.EOT
</code></pre><pre><code>@bp = @tooth_growth.ggplot(E.aes(x: :supp, <span class="hljs-attr">y</span>: :len,                                  <span class="hljs-attr">group</span>: :supp)) +       R.geom_boxplot(E.aes(fill: :supp)) +       R.facet_grid(+:all =~ +:dose) +      R.scale_fill_manual(values: R.c(<span class="hljs-string">"cyan"</span>, <span class="hljs-string">"deepskyblue4"</span>)) +      R.labs(title: <span class="hljs-string">"Tooth Growth:  Length by Dose"</span>,             <span class="hljs-attr">subtitle</span>: <span class="hljs-string">"Faceted by dose"</span>,             <span class="hljs-attr">x</span>: <span class="hljs-string">"Delivery method"</span>, <span class="hljs-attr">y</span>: <span class="hljs-string">"Teeth length"</span>,             <span class="hljs-attr">caption</span>: caption) +      CorpTheme.global_theme(faceted: <span class="hljs-literal">true</span>)
</code></pre><pre><code>puts @bp
</code></pre><pre><code>R.dev__off
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/6iMWF1Enn8Gtyym4W18120V2ca4UZWvgo8m1" alt="Image" width="540" height="560" loading="lazy">
<em>Figure 11: New plot with the same ‘corporate’ look and feel</em></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this article, we introduce Galaaz and show how to tightly couple Ruby and R in a way that Ruby developers do not need to be aware of the executing R engine. For the Ruby developer the existence of R is of no consequence, she is just coding in Ruby. On the other hand, for the R developer, migration to Ruby is a matter of small syntactic changes with a very gentle learning curve. As the R developer becomes more proficient in Ruby, he can start using ‘classes’, ‘modules’, ‘procs’, ‘lambdas’.</p>
<p>Trying to bring to Ruby the power of R starting from scratch is an enormous endeavor and would probably never be accomplished. Today’s data scientists would certainly stick with either Python or R. Now, both the Ruby and R communities can benefit from this marriage, provided by Galaaz on top of GraalVM and Truffle’s polyglot environment.</p>
<p>We developed the coupling of Ruby and R, but the process we used can also be done to couple Ruby and JavaScript or Ruby and Python. In a polyglot world we believe that a <em>uniglot</em> library might be extremely relevant.</p>
<p>From the perspective of performance, GraalVM and Truffle promises improvements that could reach over 10 times, both for <a target="_blank" href="https://medium.com/graalvm/faster-r-with-fastr-4b8db0e0dceb">FastR</a> and for <a target="_blank" href="https://rubykaigi.org/2018/presentations/eregontp.html">TruffleRuby</a>.</p>
<p>This article has shown how to improve a plot step-by-step. Starting from a very simple boxplot with all default configurations, we moved slowly to our final plot. The important point here is not if the final plot is actually beautiful (as beauty is in the eye of the beholder), but that there is a process of small steps improvements that can be followed to getting a final plot ready for presentation.</p>
<p>Finally, this whole article was written in rmarkdown and compiled to HTML by <em>gknit</em>, an application that wraps <em>knitr</em> and allows documenting Ruby code. This application can be of great help for any Rubyist trying to write articles, blogs or documentation for Ruby.</p>
<h3 id="heading-installing-galaaz">Installing Galaaz</h3>
<h4 id="heading-prerequisites">Prerequisites</h4>
<ul>
<li>GraalVM (&gt;= rc8<a target="_blank" href="https://github.com/oracle/graal/releases">): https://github.com/oracle/graal/relea</a>ses</li>
<li>TruffleRuby</li>
<li>FastR</li>
</ul>
<p>The following R packages will be automatically installed when necessary, but could be installed prior to using gKnit if desired:</p>
<ul>
<li>ggplot2</li>
<li>gridExtra</li>
<li>knitr</li>
</ul>
<p>Installation of R packages requires a development environment and can be time consuming. In Linux, the gnu compiler and tools should be enough. I am not sure what is needed on the Mac.</p>
<p>In order to run the ‘specs’ the following Ruby package is necessary:</p>
<ul>
<li>gem install rspec</li>
</ul>
<h4 id="heading-preparation">Preparation</h4>
<ul>
<li>gem install galaaz</li>
</ul>
<h3 id="heading-usage">Usage</h3>
<ul>
<li>gknit </li>
<li>In a scrip add: require ‘galaaz’</li>
</ul>
<h3 id="heading-running-the-demos">Running the demos</h3>
<p>After installation, many galaaz demos are available doing:</p>
<pre><code>&gt; galaaz -T
</code></pre><p>will show a list with all available demos. To run any of the demos in the list, substitute the call to ‘rake’ to ‘galaaz’. For instance, one of the examples in the list is ‘rake sthda:bar’. In order to run this example just do ‘galaaz sthda:bar’. Doing ‘galaaz sthda:all’ will run all demos in the sthda category, in this case a slide show with over 80 ggplot graphics written in Ruby.</p>
<p>Some of the examples require ‘rspec’ to be available. To install ‘rspec’ just do ‘gem install rspec’.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An introduction to web scraping using R ]]>
                </title>
                <description>
                    <![CDATA[ By Hiren Patel With the e-commerce boom, businesses have gone online. Customers, too, look for products online. Unlike the offline marketplace, a customer can compare the price of a product available at different places in real time. Therefore, compe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/an-introduction-to-web-scraping-using-r-40284110c848/</link>
                <guid isPermaLink="false">66c3447042d4db64acf4cbd4</guid>
                
                    <category>
                        <![CDATA[ Web Data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web crawler  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web scraping ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Oct 2018 21:25:46 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*6rTkBvVUjHucU285U1-6sw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Hiren Patel</p>
<p>With the e-commerce boom, businesses have gone online. Customers, too, look for products online. Unlike the offline marketplace, a customer can compare the price of a product available at different places in real time.</p>
<p>Therefore, competitive pricing is something that has become the most crucial part of a business strategy.</p>
<p>In order to keep prices of your products competitive and attractive, you need to monitor and keep track of prices set by your competitors. If you know what your competitors’ pricing strategy is, you can accordingly align your pricing strategy to get an edge over them.</p>
<p>Hence, price monitoring has become a vital part of the process of running an e-commerce business.</p>
<p>You might wonder how to get hold of the data to compare prices.</p>
<h3 id="heading-the-top-3-ways-of-getting-the-data-you-need-for-price-comparison">The top 3 ways of getting the data you need for price comparison</h3>
<h4 id="heading-1-feeds-from-merchants">1. Feeds from Merchants</h4>
<p>As you might be aware, there are several price comparison sites available on the internet. These sites get into a sort of understanding with the businesses wherein they get the data directly from them and which they use for price comparison.</p>
<p>These businesses put into place an API, or utilize FTP to provide the data. Generally, a referral commission is what makes a price comparison site financially viable.</p>
<h4 id="heading-2-product-feeds-from-third-party-apis">2. Product feeds from third-party APIs</h4>
<p>On the other hand, there are services which offer e-commerce data through an API. When such a service is used, the third party pays for the volume of data.</p>
<h4 id="heading-3-web-scraping">3. Web Scraping</h4>
<p><a target="_blank" href="http://www.prowebscraper.com/blog/the-ultimate-guide-to-web-scraping-for-non-programmers/">Web scraping</a> is one of the most robust and reliable ways of getting web data from the internet. It is increasingly used in price intelligence because it is an efficient way of getting the product data from e-commerce sites.</p>
<p>You may not have access to the first and second option. Hence, web scraping can come to your rescue. You can use web scraping to leverage the power of data to arrive at competitive pricing for your business.</p>
<p>Web scraping can be used to get current prices for the current market scenario, and e-commerce more generally. We will use web scraping to get the data from an e-commerce site. In this blog, you will learn how to scrape the names and prices of products from Amazon in all categories, under a particular brand.</p>
<p>Extracting data from Amazon periodically can help you keep track of the market trends of pricing and enable you to set your prices accordingly.</p>
<h3 id="heading-table-of-contents">Table of contents</h3>
<ol>
<li><a target="_blank" href="https://medium.com/p/40284110c848#45c6">Web scraping for price comparison</a></li>
<li><a target="_blank" href="https://medium.com/p/40284110c848#ed51">Web scraping in R</a></li>
<li><a target="_blank" href="https://medium.com/p/40284110c848#5130">Implementation</a></li>
<li><a target="_blank" href="https://medium.com/p/40284110c848#b3ba">End note</a></li>
</ol>
<h3 id="heading-1-web-scraping-for-price-comparison">1. Web scraping for price comparison</h3>
<p>As the market wisdom says, price is everything. The customers make their purchase decisions based on price. They base their understanding of the quality of a product on price. In short, price is what drives the customers and, hence, the market.</p>
<p>Therefore, <strong>price comparison sites</strong> are in great demand. Customers can easily navigate the whole market by looking at the prices of the same product across the brands. These price comparison websites extract the price of the same product from different sites.</p>
<p>Along with price, price comparison websites also scrape data such as the product description, technical specifications, and features. They project the whole gamut of information on a single page in a comparative way.</p>
<p>This answers the question the prospective buyer has asked in their search. Now the prospective buyer can compare the products and their prices, along with information such as features, payment, and shipping options, so that they can identify the best possible deal available.</p>
<p>Pricing optimization has its impact on the business in the sense that such techniques can enhance profit margins by 10%.</p>
<p>E-commerce is all about competitive pricing, and it has spread to other business domains as well. Take the case of travel. Now even travel-related websites scrape the price from airline websites <strong>in real time</strong> to provide the price comparison of different airlines.</p>
<p>The only challenge in this is to update the data in real time and stay up to date every second as prices keep changing on the source sites. Price comparison sites use Cron jobs or at the view time to update the price. However, it will rest upon the configuration of the site owner.</p>
<p>This is where this blog can help you — you will be able to work out a scraping script that you can customize to suit your needs. You will be able to extract product feeds, images, price, and all other relevant details regarding a product from a number of different websites. With this, you can create your powerful database for price comparison site.</p>
<h3 id="heading-2-web-scraping-in-r">2. Web scraping in R</h3>
<p>Price comparison becomes cumbersome because getting web data is not that easy — there are technologies like HTML, XML, and JSON to distribute the content.</p>
<p>So, in order to get the data you need, you must effectively navigate through these different technologies. R can help you access data stored in these technologies. However, it requires a bit of in-depth understanding of R before you get started.</p>
<h4 id="heading-what-is-r">What is R?</h4>
<p>Web scraping is an advanced task that not many people perform. Web scraping with R is, certainly, technical and advanced programming. An adequate understanding of R is essential for web scraping in this way.</p>
<p>To start with, R is a language for statistical computing and graphics. Statisticians and data miners use R a lot due to its evolving statistical software, and its focus on data analysis.</p>
<p>One reason R is such a favorite among this set of people is the quality of plots which can be worked out, including mathematical symbols and formulae wherever required.</p>
<p>R is wonderful because it offers a vast variety of functions and packages that can handle data mining tasks.</p>
<p>rvest, RCrawler etc are R packages used for data collection processes.</p>
<p>In this segment, we will see what kinds of tools are required to work with R to carry out web scraping. We will see it through the use case of Amazon website from where we will try to get the product data and store it in JSON form.</p>
<h4 id="heading-requirements">Requirements</h4>
<p>In this use case, knowledge of R is essential and I am assuming that you have <strong>a basic understanding of R</strong>. You should be aware of at least any one R interface, such as RStudio. The base R installation interface is fine.</p>
<p>If you are not aware of R and the other associated interfaces, you should go through <a target="_blank" href="https://www.tutorialspoint.com/r/index.htm">this</a> tutorial.</p>
<p>Now let’s understand how the packages we’re going to use will be installed.</p>
<h4 id="heading-packages">Packages:</h4>
<p><strong>1. <a target="_blank" href="https://cran.r-project.org/web/packages/rvest/">rvest</a></strong></p>
<p>Hadley Wickham authored the rvest package for web scraping in R. rvest is useful in extracting the information you need from web pages.</p>
<p>Along with this, you also need to install the <a target="_blank" href="https://cran.r-project.org/web/packages/selectr/">selectr</a> and ‘xml2’ packages.</p>
<p><strong>Installation steps:</strong></p>
<pre><code>install.packages(‘selectr’)
</code></pre><pre><code>install.packages(‘xml2’)
</code></pre><pre><code>install.packages(‘rvest’)
</code></pre><p>rvest contains the basic web scraping functions, which are quite effective. Using the following functions, we will try to extract the data from web sites.</p>
<ul>
<li><code>read_html(url)</code> : scrape HTML content from a given URL</li>
<li><code>html_nodes()</code>: identifies HTML wrappers.</li>
<li><code>html_nodes(“.class”)</code>: calls node based on CSS class</li>
<li><code>html_nodes(“#id”)</code>: calls node based on <div> id</div></li>
<li><code>html_nodes(xpath=”xpath”)</code>: calls node based on xpath (we’ll cover this later)</li>
<li><code>html_attrs()</code>: identifies attributes (useful for debugging)</li>
<li><code>html_table()</code>: turns HTML tables into data frames</li>
<li><code>html_text()</code>: strips the HTML tags and extracts only the text</li>
</ul>
<p><strong>2. <a target="_blank" href="https://cran.r-project.org/web/packages/stringr/">stringr</a></strong></p>
<p>stringr comes into play when you think of tasks related to data cleaning and preparation.</p>
<p>There are four essential sets of functions in stringr:</p>
<ul>
<li>stringr functions are useful because they enable you to work around the individual characters within the strings in character vectors</li>
<li>there are whitespace tools which can be used to add, remove, and manipulate whitespace</li>
<li>there are locale sensitive operations whose operations will differ from locale to locale</li>
<li>there are pattern matching functions. These functions recognize four parts of pattern description. Regular expressions are the standard one but there are other tools as well</li>
</ul>
<p><strong>Installation</strong></p>
<p><code>install.packages(‘stringr’)</code></p>
<p><strong>3. <a target="_blank" href="https://cran.r-project.org/web/packages/jsonlite/">jsonlite</a></strong></p>
<p>What makes the jsonline package useful is that it is a JSON parser/generator which is optimized for the web.</p>
<p>It is vital because it enables an effective mapping between JSON data and the crucial R data types. Using this, we are able to convert between R objects and JSON without loss of type or information, and without the need for any manual data wrangling.</p>
<p>This works really well for interacting with web APIs, or if you want to create ways through which data can travel in and out of R using JSON.</p>
<h4 id="heading-installation">Installation</h4>
<p><code>install.packages(‘jsonlite’)</code></p>
<p>Before we jump-start into it, let’s see how it works:</p>
<p>It should be clear at the outset that each website is different, because the coding that goes into a website is different.</p>
<p>Web scraping is the technique of identifying and using these patterns of coding to extract the data you need. Your browser makes the website available to you from HTML. Web scraping is simply about parsing the HTML made available to you from your browser.</p>
<p>Web scraping has a set process that works like this, generally:</p>
<ul>
<li>Access a page from R</li>
<li>Instruct R where to “look” on the page</li>
<li>Convert data in a usable format within R using the rvest package</li>
</ul>
<p>Now let’s go to implementation to understand it better.</p>
<h3 id="heading-3-implementation">3. Implementation</h3>
<p>Let’s implement it and see how it works. We will scrape the Amazon website for the price comparison of a product called “One Plus 6”, a mobile phone.</p>
<p>You can see it <a target="_blank" href="https://www.amazon.in/OnePlus-Mirror-Black-64GB-Memory/dp/B0756Z43QS?tag=googinhydr18418-21&amp;tag=googinkenshoo-21&amp;ascsubtag=aee9a916-6acd-4409-92ca-3bdbeb549f80">here</a>.</p>
<h4 id="heading-step-1-loading-the-packages-we-need">Step 1: Loading the packages we need</h4>
<p>We need to be in the console, at R command prompt to start the process. Once we are there, we need to load the packages required as shown below:</p>
<pre><code>#loading the package:&gt; library(xml2)&gt; library(rvest)&gt; library(stringr)
</code></pre><h4 id="heading-step-2-reading-the-html-content-from-amazon">Step 2: Reading the HTML content from Amazon</h4>
<pre><code>#Specifying the url <span class="hljs-keyword">for</span> desired website to be scrappedurl &lt;- ‘https:<span class="hljs-comment">//www.amazon.in/OnePlus-Mirror-Black-64GB-Memory/dp/B0756Z43QS?tag=googinhydr18418-21&amp;tag=googinkenshoo-21&amp;ascsubtag=aee9a916-6acd-4409-92ca-3bdbeb549f80’</span>
</code></pre><pre><code>#Reading the html content <span class="hljs-keyword">from</span> Amazonwebpage &lt;- read_html(url)
</code></pre><p>In this code, we read the HTML content from the given URL, and assign that HTML into the <code>webpage</code> variable.</p>
<h4 id="heading-step-3-scrape-product-details-from-amazon">Step 3: Scrape product details from Amazon</h4>
<p>Now, as the next step, we will extract the following information from the website:</p>
<p><strong>Title:</strong> The title of the product.<br><strong>Price:</strong> The price of the product.<br><strong>Description:</strong> The description of the product.<br><strong>Rating:</strong> The user rating of the product.<br><strong>Size:</strong> The size of the product.<br><strong>Color:</strong> The color of the product.</p>
<p>This screenshot shows how these fields are arranged.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/pkjBWv02tpI-K7rmIfaXVHpaOyAe1EEntazu" alt="Image" width="800" height="433" loading="lazy"></p>
<p>Next, we will make use of HTML tags, like the title of the product and price, for extracting data using Inspect Element.</p>
<p>In order to find out the class of the HTML tag, use the following steps:</p>
<p><strong>=&gt; go to chrome browser =&gt; <a target="_blank" href="https://www.amazon.in/OnePlus-Mirror-Black-64GB-Memory/dp/B0756Z43QS?tag=googinhydr18418-21&amp;tag=googinkenshoo-21&amp;ascsubtag=aee9a916-6acd-4409-92ca-3bdbeb549f80">go t</a>o this URL =&gt; right click =&gt; ins</strong>pect element</p>
<p>NOTE: If you are not using the Chrome browser, check out this <a target="_blank" href="https://www.lifewire.com/get-inspect-element-tool-for-browser-756549">article</a>.</p>
<p>Based on CSS selectors such as class and id, we will scrape the data from the HTML. To find the CSS class for the product title, we need to right-click on title and select “Inspect” or “Inspect Element”.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Flm5Bs2obtKKuzvfITUik-KvxXLCeoOoFQQe" alt="Image" width="800" height="350" loading="lazy"></p>
<p>As you can see below, I extracted the title of the product with the help of <code>html_nodes</code> in which I passed the id of the title — <code>h1#title</code> — and <code>webpage</code> which had stored HTML content.</p>
<p>I could also get the title text using <code>html_text</code> and print the text of the title with the help of the <code>head ()</code> function.</p>
<pre><code>#scrape title <span class="hljs-keyword">of</span> the product&gt; title_html &lt;- html_nodes(webpage, ‘h1#title’)&gt; title &lt;- html_text(title_html)&gt; head(title)
</code></pre><p>The output is shown below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/QyHXYYJnwO8XjmE0Rl7kOPuZySAWexA4Pa0G" alt="Image" width="800" height="78" loading="lazy"></p>
<p>We could get the title of the product using spaces and \n.</p>
<p>The next step would be to remove spaces and new line with the help of the <code>str_replace_all()</code> function in the stringr library.</p>
<pre><code># remove all space and <span class="hljs-keyword">new</span> linesstr_replace_all(title, “[\r\n]” , “”)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/a2hhGLdfMWUXoI1l14w50EPTpn3gDaQqFZ3E" alt="Image" width="800" height="84" loading="lazy"></p>
<p>Now we will need to extract the other related information of the product following the same process.</p>
<p><strong>Price of the product:</strong></p>
<pre><code># scrape the price <span class="hljs-keyword">of</span> the product&gt; price_html &lt;- html_nodes(webpage, ‘span#priceblock_ourprice’)&gt; price &lt;- html_text(price_html)
</code></pre><pre><code># remove spaces and <span class="hljs-keyword">new</span> line&gt; str_replace_all(title, “[\r\n]” , “”)
</code></pre><pre><code># print price value&gt; head(price)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BaQkWbhiOTbEcPPE8yDxCUOxYNzQcA-Hjbid" alt="Image" width="800" height="59" loading="lazy"></p>
<p><strong>Product description:</strong></p>
<pre><code># scrape product description&gt; desc_html &lt;- html_nodes(webpage, ‘div#productDescription’)&gt; desc &lt;- html_text(desc_html)
</code></pre><pre><code># replace <span class="hljs-keyword">new</span> lines and spaces&gt; desc &lt;- str_replace_all(desc, “[\r\n\t]” , “”)&gt; desc &lt;- str_trim(desc)&gt; head(desc)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4rRvYGeRcPvmIUfinTn2bXKREpb8GEOTkohp" alt="Image" width="800" height="62" loading="lazy"></p>
<p><strong>Rating of the product:</strong></p>
<pre><code># scrape product rating &gt; rate_html &lt;- html_nodes(webpage, ‘span#acrPopover’)&gt; rate &lt;- html_text(rate_html)
</code></pre><pre><code># remove spaces and newlines and tabs &gt; rate &lt;- str_replace_all(rate, “[\r\n]” , “”)&gt; rate &lt;- str_trim(rate)
</code></pre><pre><code># print rating <span class="hljs-keyword">of</span> the product&gt; head(rate)
</code></pre><p>Output<strong>:</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AaFCC2rDSdUbkhwe191ZEuvW61Qkg7DMjbkA" alt="Image" width="588" height="46" loading="lazy"></p>
<p><strong>Size of the product:</strong></p>
<pre><code># Scrape size <span class="hljs-keyword">of</span> the product&gt; size_html &lt;- html_nodes(webpage, ‘div#variation_size_name’)&gt; size_html &lt;- html_nodes(size_html, ‘span.selection’)&gt; size &lt;- html_text(size_html)
</code></pre><pre><code># remove tab <span class="hljs-keyword">from</span> text&gt; size &lt;- str_trim(size)
</code></pre><pre><code># Print product size&gt; head(size)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/kCt3GDbF097jzs-5iki5BFnkvsUZW7kIjf4h" alt="Image" width="496" height="46" loading="lazy"></p>
<p><strong>Color of the product:</strong></p>
<pre><code># Scrape product color&gt; color_html &lt;- html_nodes(webpage, ‘div#variation_color_name’)&gt; color_html &lt;- html_nodes(color_html, ‘span.selection’)&gt; color &lt;- html_text(color_html)
</code></pre><pre><code># remove tabs <span class="hljs-keyword">from</span> text&gt; color &lt;- str_trim(color)
</code></pre><pre><code># print product color&gt; head(color)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/t0NsecrDY9EcA4a2fy9yoZaFujN3ZVNsKEHz" alt="Image" width="590" height="47" loading="lazy"></p>
<h4 id="heading-step-4-we-have-successfully-extracted-data-from-all-the-fields-which-can-be-used-to-compare-the-product-information-from-another-site">Step 4: We have successfully extracted data from all the fields which can be used to compare the product information from another site.</h4>
<p>Let’s compile and combine them to work out a dataframe and inspect its structure.</p>
<pre><code>#Combining all the lists to form a data frameproduct_data &lt;- data.frame(Title = title, Price = price,Description = desc, Rating = rate, Size = size, Color = color)
</code></pre><pre><code>#Structure <span class="hljs-keyword">of</span> the data framestr(product_data)
</code></pre><p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FcmJzO0w75kaurbce4JBCLRvPuYiLIhP3NO8" alt="Image" width="800" height="153" loading="lazy"></p>
<p>In this output we can see all the scraped data in the data frames.</p>
<h4 id="heading-step-5-store-data-in-json-format">Step 5: Store data in JSON format:</h4>
<p>As the data is collected, we can carry out different tasks on it such as compare, analyze, and arrive at business insights about it. Based on this data, we can think of training machine learning models over this.</p>
<p>Data would be stored in JSON format for further process.</p>
<p>Follow the given code and get the JSON result.</p>
<pre><code># Include ‘jsonlite’ library to convert <span class="hljs-keyword">in</span> <span class="hljs-built_in">JSON</span> form.&gt; library(jsonlite)
</code></pre><pre><code># convert dataframe into <span class="hljs-built_in">JSON</span> format&gt; json_data &lt;- toJSON(product_data)
</code></pre><pre><code># print output&gt; cat(json_data)
</code></pre><p>In the code above, I have included <code>jsonlite</code> library for using the <code>toJSON()</code> function to convert the dataframe object into JSON form.</p>
<p>At the end of the process, we have stored data in JSON format and printed it.<br>It is possible to store data in a csv file also or in the database for further processing, if we wish.</p>
<p>Output:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/U9xauMDxyvYfXFjq5TLk-hn11A85f6UO3O4c" alt="Image" width="800" height="122" loading="lazy"></p>
<p>Following this practical example, you can also extract the relevant data for the same from product from <a target="_blank" href="https://www.oneplus.in/6">https://www.oneplus.in/6</a> and compare with Amazon to work out the fair value of the product. In the same way, you can use the data to compare it with other websites.</p>
<h3 id="heading-4-end-note">4. End note</h3>
<p>As you can see, R can give you great leverage in scraping data from different websites. With this practical illustration of how R can be used, you can now explore it on your own and extract product data from Amazon or any other e-commerce website.</p>
<p>A word of caution for you: <strong>certain websites have anti-scraping policies</strong>. If you overdo it, you will be blocked and you will begin to see captchas instead of product details. Of course, you can also learn to work your way around the captchas using different services available. However, you do need to understand the <a target="_blank" href="http://www.prowebscraper.com/blog/six-compelling-facts-about-legality-of-web-scraping/">legality of scraping</a> data and whatever you are doing with the scraped data.</p>
<p>Feel free to send to me your feedback and suggestions regarding this post!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Finding Correlations in Non-Linear Data ]]>
                </title>
                <description>
                    <![CDATA[ By Peter Gleeson From a signalling perspective, the world is a noisy place. In order to make sense of anything, we have to be selective with our attention. We humans have, over the course of millions of years of natural selection, become fairly good ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-machines-make-predictions-finding-correlations-in-complex-data-dfd9f0d87889/</link>
                <guid isPermaLink="false">66d4609bd14641365a05094d</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ statistics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 29 Jan 2018 21:26:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9cb0a8740569d1a4cab5c2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Peter Gleeson</p>
<p>From a signalling perspective, the world is a noisy place. In order to make sense of anything, we have to be selective with our attention.</p>
<p>We humans have, over the course of millions of years of natural selection, become fairly good at filtering out background signals. We learn to associate particular signals with certain events.</p>
<p>For instance, imagine you’re playing table tennis in a busy office.</p>
<p>To return your opponent’s shot, you need to make a huge array of complex calculations and judgements, taking into account multiple competing sensory signals.</p>
<p>To predict the motion of the ball, your brain has to repeatedly sample the ball’s current position and estimate its future trajectory. More advanced players will also take into account any spin their opponent applied to the shot.</p>
<p>Finally, in order to play your own shot, you need to account for the position of your opponent, your own position, the speed of the ball, and any spin you intend to apply.</p>
<p>All of this involves an amazing amount of subconscious differential calculus. We take it for granted that, generally speaking, our nervous system can do this automatically (at least after a bit of practice).</p>
<p>Just as impressive is how the human brain differentially assigns importance to each of the myriad competing signals it receives. The position of the ball, for example, is judged to be more relevant than, say, the conversation taking place behind you, or the door opening in front of you.</p>
<p>This may sound so obvious as to seem unworthy of stating, but that is testament to the just how good we are at learning to make accurate predictions out of noisy data.</p>
<p>Certainly, a blank-state machine given a continuous stream of audiovisual data would face a difficult task knowing which signals best predict the optimal course of action.</p>
<p>Luckily, there are statistical and computational methods that can be used to identify patterns in noisy, complex data.</p>
<h3 id="heading-correlation-101">Correlation 101</h3>
<p>Generally speaking, when we talk of ‘correlation’ between two variables, we are referring to their ‘relatedness’ in some sense.</p>
<p>Correlated variables are those which contain information about each other. The stronger the correlation, the more one variable tells us about the other.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*T40Se1iQZKEVGe4q4MTWPw.png" alt="Image" width="800" height="260" loading="lazy">
<em>You may have seen it all before: Positive correlation, zero correlation, negative correlation</em></p>
<p>You may well already have some understanding of correlation, how it works and what its limitations are. Indeed, it’s something of a data science cliche:</p>
<blockquote>
<p>“Correlation does not imply causation”</p>
</blockquote>
<p>This is of course true — there are good reasons why even a strong correlation between two variables is not a guarantor of causality. The observed correlation could be due to the effects of a hidden third variable, or just entirely down to chance.</p>
<p>That said, correlation <em>does allow</em> for predictions about one variable to made based upon another. There are several methods that can be used to estimate correlated-ness for both linear and non-linear data. Let’s take a look at how they work.</p>
<p>We’ll go through the math and the code implementation, using Python and R. The code for the examples this article can be found <a target="_blank" href="https://gist.github.com/anonymous/fabecccf33f9c3feb568384f626a2c07">here</a>.</p>
<h3 id="heading-pearsons-correlation-coefficient">Pearson’s Correlation Coefficient</h3>
<h4 id="heading-what-is-it">What is it?</h4>
<p>Pearson’s Correlation Coefficient (PCC, or Pearson’s <em>r</em>) is a widely used linear correlation measure. It’s often the first one taught in many elementary stats courses. Mathematically speaking, it is defined as “the covariance between two vectors, normalized by the product of their standard deviations”.</p>
<h4 id="heading-tell-me-more">Tell me more…</h4>
<p>The covariance between two paired vectors is a measure of their tendency to vary above or below their means together. That is, a measure of whether each pair tend to be on similar or opposite sides of their respective means.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*w-05-YnuJMl84KMSRw1J2g.png" alt="Image" width="800" height="166" loading="lazy"></p>
<p>Let’s see this implemented in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mean</span>(<span class="hljs-params">x</span>):</span>
    <span class="hljs-keyword">return</span> sum(x)/len(x)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">covariance</span>(<span class="hljs-params">x,y</span>):</span>
    calc = []
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(x)):
        xi = x[i] - mean(x)
        yi = y[i] - mean(y)
        calc.append(xi * yi)
    <span class="hljs-keyword">return</span> sum(calc)/(len(x) - <span class="hljs-number">1</span>)

a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>] ; b = [<span class="hljs-number">5</span>,<span class="hljs-number">4</span>,<span class="hljs-number">3</span>,<span class="hljs-number">2</span>,<span class="hljs-number">1</span>]
print(covariance(a,b))
</code></pre>
<p>The covariance is calculated by taking each pair of variables, and subtracting their respective means from them. Then, multiply these two values together.</p>
<ul>
<li>If they are both above their mean (or both below), then this will produce a positive number, because a positive×positive=positive, and likewise a negative×negative=positive.</li>
<li>If they are on different sides of their means, then this produces a negative number (because positive×negative=negative).</li>
</ul>
<p>Once we have all these values calculated for each pair, sum them up, and divide by <em>n-1</em>, where <em>n</em> is the sample size. This is the <strong>sample covariance</strong>.</p>
<p>If the pairs have a tendency to both be on the same side of their respective means, the covariance will be a positive number. If they have a tendency to be on opposite sides of their means, the covariance will be a negative number. The stronger this tendency, the larger the absolute value of the covariance.</p>
<p>If there is no overall pattern, then the covariance will be close to zero. This is because the positive and negative values will cancel each other out.</p>
<p>At first, it might appear that the covariance is a sufficient measure of ‘relatedness’ between two variables. However, take a look at the graph below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0*JcDgGdi7a3WrElG4.png" alt="Image" width="800" height="473" loading="lazy">
_Covariance = 0.00003. From a [question posted recently on stackexchange](https://stats.stackexchange.com/questions/320001/why-does-this-set-of-data-have-no-covariance" rel="noopener" target="<em>blank" title=")</em></p>
<p>Looks like there’s a strong relationship between the variables, right? So why is the covariance so low, at approximately 0.00003?</p>
<p>The key here is to realise that the covariance is scale-dependent. Look at the <em>x</em> and <em>y</em> axes — pretty much all the data points fall between the range of 0.015 and 0.04. The covariance is likewise going to be close to zero, since it is calculated by subtracting the means from each individual observation.</p>
<p>To obtain a more meaningful figure, it is important to <em>normalize</em> the covariance. This is done by dividing it by the product of the standard deviations of each of the vectors.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*0-hwOw2u7IXD9cNd_bVfTg.png" alt="Image" width="800" height="245" loading="lazy">
<em>The Greek letter rho is often used to denote Pearson’s r</em></p>
<p>In Python:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stDev</span>(<span class="hljs-params">x</span>):</span>
    variance = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> x:
        variance += (i - mean(x) ** <span class="hljs-number">2</span>) / len(x)
    <span class="hljs-keyword">return</span> math.sqrt(variance)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">Pearsons</span>(<span class="hljs-params">x,y</span>):</span>
    cov = covariance(x,y)
    <span class="hljs-keyword">return</span> cov / (stDev(x) * stDev(y))
</code></pre>
<p>The reason this is done is because the standard deviation of a vector is the square root of its variance. This means if two vectors are identical, then multiplying their standard deviations will equal their variance.</p>
<p>Funnily enough, the covariance of two identical vectors is also equal to their variance.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*-RGxvvVyuq_jxqaCp8UgDA.png" alt="Image" width="800" height="187" loading="lazy"></p>
<p>Therefore, the maximum value the covariance between two vectors can take is equal to the product of their standard deviations, which occurs when the vectors are perfectly correlated. It is this which bounds the correlation coefficient between -1 and +1.</p>
<h4 id="heading-which-way-do-the-arrows-point">Which way do the arrows point?</h4>
<p>As an aside, a much cooler way of defining the PCC of two vectors comes from linear algebra.</p>
<p>First, we center the vectors, by subtracting their means from their individual values.</p>
<pre><code class="lang-python">a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>] ; b = [<span class="hljs-number">5</span>,<span class="hljs-number">4</span>,<span class="hljs-number">3</span>,<span class="hljs-number">2</span>,<span class="hljs-number">1</span>]

a_centered = [i - mean(a) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> a]
b_centered = [j - mean(b) <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> b]
</code></pre>
<p>Now, we can make use of the fact that vectors can be considered as ‘arrows’ pointing in a given direction.</p>
<p>For instance, in 2-D, the vector [1,3] could be represented as an arrow pointing 1 unit along the x-axis, and 3 units along the y-axis. Likewise, the vector [2,1] could be represented as an arrow pointing 2 units along the x-axis, and 1 unit along the y-axis.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*svjyR3aNxIVX1ORP9X_ncA.png" alt="Image" width="800" height="363" loading="lazy">
<em>Two vectors (1,3) and (2,1) shown as arrows.</em></p>
<p>Similarly, we can represent our data vectors as arrows in an <em>n</em>-dimensional space (although don’t try visualising when <em>n</em> &gt; 3…)</p>
<p>The angle ϴ between these arrows can be worked out using the <strong>dot product</strong> of the two vectors. This is defined as:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*tvzSMv4WDkq4JaigjN8hEw.png" alt="Image" width="800" height="128" loading="lazy"></p>
<p>Or, in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">dotProduct</span>(<span class="hljs-params">x,y</span>):</span>
    calc = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(x)):
        calc += x[i] * y[i]
    <span class="hljs-keyword">return</span> calc
</code></pre>
<p>The dot product can also be defined as:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*xf5f2-tOTyW8iMgPWZ1rXw.png" alt="Image" width="800" height="124" loading="lazy"></p>
<p>Where ||<strong>x</strong>|| is the magnitude (or ‘length’) of the vector <strong>x</strong> (think <a target="_blank" href="https://www.mathplanet.com/education/pre-algebra/right-triangles-and-algebra/the-pythagorean-theorem">Pythagoras’ theorem</a>), and ϴ is the angle between the arrow vectors.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*KV1zvh0Yqp0eHyJrYzcHQw.png" alt="Image" width="800" height="161" loading="lazy"></p>
<p>As a Python function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">magnitude</span>(<span class="hljs-params">x</span>):</span>
    x_sq = [i ** <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> x]
    <span class="hljs-keyword">return</span> math.sqrt(sum(x_sq))
</code></pre>
<p>This lets us find cos(ϴ), by dividing the dot product by the product of the magnitudes of the two vectors.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*TrH91rL7SmW5b_nPkyQcxg.png" alt="Image" width="800" height="153" loading="lazy"></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cosTheta</span>(<span class="hljs-params">x,y</span>):</span>
    mag_x = magnitude(x)
    mag_y = magnitude(y)
    <span class="hljs-keyword">return</span> dotProduct(x,y) / (mag_x * mag_y)
</code></pre>
<p>Now, if you know a little trigonometry, you may recall that the cosine function produces a graph that oscillates between +1 and -1.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ePSqr56-PVAiUKeF9MqITA.gif" alt="Image" width="700" height="192" loading="lazy">
_[Source](http://cda.mrs.umn.edu/~mcquarrb/teachingarchive/Precalculus/Animations/SineCosineAnim.html" rel="noopener" target="<em>blank" title=")</em></p>
<p>The value of cos(ϴ) will vary depending on the angle between the two arrow vectors.</p>
<ul>
<li>When the angle is zero (i.e., the vectors point in the exact same direction), cos(ϴ) will equal 1.</li>
<li>When the angle is -180°, (the vectors point in exact opposite directions), then cos(ϴ) will equal -1.</li>
<li>When the angle is 90° (the vectors point in completely unrelated directions), then cos(ϴ) will equal zero.</li>
</ul>
<p>This might look familiar — a measure between +1 and -1 that seems to describe the relatedness of two vectors? Isn’t that Pearson’s <em>r</em>?</p>
<p>Well — that is exactly what it is! By considering the data as arrow vectors in a high-dimensional space, we can use the angle ϴ between them as a measure of similarity.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LLm4XA_SQVwXDm5r8SloxQ.png" alt="Image" width="800" height="250" loading="lazy">
<em>A) Positively correlated vectors; B) Negatively correlated vectors; C) Uncorrelated vectors</em></p>
<p>The cosine of this angle ϴ is mathematically <em>identical</em> to Pearson’s Correlation Coefficient.</p>
<p>When viewed as high-dimensional arrows, positively correlated vectors will point in a similar direction.</p>
<p>Negatively correlated vectors will point towards opposite directions.</p>
<p>And uncorrelated vectors will point at right-angles to one another.</p>
<p>Personally, I think this is a really intuitive way to make sense of correlation.</p>
<h4 id="heading-statistical-significance">Statistical significance?</h4>
<p>As is always the case with frequentist statistics, it is important to ask how significant a test statistic calculated from a given sample actually is. Pearson’s <em>r</em> is no exception.</p>
<p>Unfortunately, whacking confidence intervals on an estimate of PCC is not entirely straightforward.</p>
<p>This is because Pearson’s <em>r</em> is bound between -1 and +1, and therefore isn’t normally distributed. An estimated PCC of, say, +0.95 has only so much room for error above it, but plenty of room below.</p>
<p>Luckily, there is a solution — using a trick called Fisher’s Z-transform:</p>
<ol>
<li>Calculate an estimate of Pearson’s <em>r</em> as usual.</li>
<li>Transform <em>r</em>→<em>z</em> using Fisher’s Z-transform. This can be done by using the formula <em>z</em> = arctanh(<em>r</em>), where arctanh is the <a target="_blank" href="http://mathworld.wolfram.com/InverseHyperbolicTangent.html">inverse hyperbolic tangent function</a>.</li>
<li>Now calculate the standard deviation of <em>z</em>. Luckily, this is straightforward to calculate, and is given by SD<em>z</em> = 1/sqrt(<em>n</em>-3), where <em>n</em> is the sample size.</li>
<li>Choose your significance threshold, alpha, and check how many standard deviations from the mean this corresponds to. If we take alpha = 0.95, use 1.96.</li>
<li>Find the upper estimate by calculating <em>z</em> +(1.96 × SD<em>z</em>), and the lower bound by calculating <em>z -</em> (1.96 × SD<em>z</em>)<em>.</em></li>
<li>Convert these back to <em>r,</em> using <em>r</em> = tanh(<em>z</em>), where tanh is the <a target="_blank" href="http://mathworld.wolfram.com/HyperbolicTangent.html">hyperbolic tangent function</a>.</li>
<li>If the upper and lower bounds are both the same side of zero, you have statistical significance!</li>
</ol>
<p>Here’s a Python implementation:</p>
<pre><code class="lang-python">r = Pearsons(x,y)
z = math.atanh(r)
SD_z = <span class="hljs-number">1</span> / math.sqrt(len(x) - <span class="hljs-number">3</span>)
z_upper = z + <span class="hljs-number">1.96</span> * SD_z
z_lower = z - <span class="hljs-number">1.96</span> * SD_z
r_upper = math.tanh(z_upper)
r_lower = math.tanh(z_lower)
</code></pre>
<p>Of course, when given a large data set of many potentially correlated variables, it may be tempting to check every pairwise correlation. This is often referred to as ‘data dredging’ — scouring the data set for any apparent relationships between the variables.</p>
<p>If you do take this multiple comparison approach, you should use stricter significance thresholds to reduce your risk of discovering false positives (that is, finding unrelated variables which appear correlated purely by chance).</p>
<p>One method for doing this is to use the <a target="_blank" href="https://matthew-brett.github.io/teaching/bonferroni_correction.html#the-bonferroni-correction">Bonferroni correction</a>.</p>
<h4 id="heading-the-small-print">The small print</h4>
<p>So far, so good. We’ve seen how Pearson’s <em>r</em> can be used to calculate the correlation coefficient between two variables, and how to assess the statistical significance of the result. Given an unseen set of data, it is possible to start mining for significant relationships between the variables.</p>
<p>However, there is a major catch — Pearson’s <em>r</em> only works for linear data.</p>
<p>Look at the graphs below. They clearly show what looks like a non-random relationship, but Pearson’s <em>r</em> is very close to zero.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Ns2wlo3CeJaVaTJ56CS8QA.png" alt="Image" width="800" height="328" loading="lazy"></p>
<p>The reason why is because the variables in these graphs have a <em>non-linear</em> relationship.</p>
<p>We can generally picture a relationship between two variables as a ‘cloud’ of points scattered either side of a line. The wider the scatter, the ‘noisier’ the data, and the weaker the relationship.</p>
<p>However,  Pearson’s <em>r</em> compares each individual data point with only one other (the overall means). This means it can only consider straight lines. It’s not great at detecting any non-linear relationships.</p>
<p>In the graphs above, Pearson’s <em>r</em> doesn’t reveal there being much correlation to talk of.</p>
<p>Yet the relationship between these variables is still clearly non-random, and that makes them potentially useful predictors of each other. How can machines identify this? Luckily, there are different correlation measures available to us.</p>
<p>Let’s take a look at a couple of them.</p>
<h3 id="heading-distance-correlation">Distance Correlation</h3>
<h4 id="heading-what-is-it-1">What is it?</h4>
<p><a target="_blank" href="https://projecteuclid.org/download/pdfview_1/euclid.aos/1201012979">Distance correlation</a> bears some resemblance to Pearson’s <em>r</em>, but is actually calculated using a rather different notion of covariance. The method works by replacing our everyday concepts of covariance and standard deviation (as defined above) with “distance” analogues.</p>
<p>Much like Pearson’s <em>r</em>, “distance correlation” is defined as the “distance covariance” normalized by the “distance standard deviation”.</p>
<p>Instead of assessing how two variables tend to co-vary in their distance from their respective means, distance correlation assesses how they tend to co-vary in terms of their distances from all other points.</p>
<p>This opens up the potential to better capture non-linear dependencies between variables.</p>
<h4 id="heading-the-finer-details">The finer details…</h4>
<p>Robert Brown was a Scottish botanist born in 1773. While studying plant pollen under his microscope, Brown noticed tiny organic particles jittering about at random on the surface of the water he was using.</p>
<p>Little could he have suspected a chance observation of his would lead to his name being immortalized as the (re-)discoverer of Brownian motion.</p>
<p>Even less could he have known that it would take nearly a century before Albert Einstein would provide <a target="_blank" href="http://galileo.phys.virginia.edu/classes/152.mf1i.spring02/BrownianMotion.htm">an explanation for the phenomenon</a> — and hence proving the existence of atoms — in the same year he published papers on E=MC², special relativity and helped kick-start the field of quantum theory.</p>
<p>Brownian motion is a physical process whereby particles move about at random due to collisions with surrounding molecules.</p>
<p>The math behind this process can be generalized into a concept known as the <a target="_blank" href="http://mathworld.wolfram.com/WienerProcess.html">Weiner process</a>. Among other things, the Weiner process plays an important part in mathematical finance’s most famous model, <a target="_blank" href="https://www.investopedia.com/terms/b/blackscholes.asp">Black-Scholes</a>.</p>
<p>Interestingly, Brownian motion and the Weiner process turn out to be relevant to a non-linear correlation measure developed in the mid-2000’s through the work of Gabor Szekely.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*yVRBk0RhkIO-cs6-WDKgQQ.png" alt="Image" width="800" height="148" loading="lazy"></p>
<p>Let’s run through how this can be calculated for two vectors <em>x</em> and <em>y</em>, each of length <em>N</em>.</p>
<ol>
<li>First, we form <em>N</em>×<em>N</em> distance matrices for each of the vectors. A distance matrix is exactly like a road distance chart in an atlas — the intersection of each row and column shows the distance between the corresponding cities. Here, the intersection between row <em>i</em> and column <em>j</em> gives the distance between the i-th and j-th elements of the vector.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Grvyk2jd7ZPb9_1GcB0zbQ.png" alt="Image" width="800" height="125" loading="lazy"></p>
<ol start="2">
<li>Next, the matrices are “double-centered”. This means for each element, we subtract the mean of its row and the mean of its column. Then, we add the grand mean of the entire matrix.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*KAptj_a0yXBHwApaCOjJug.png" alt="Image" width="800" height="232" loading="lazy">
<em>The ‘hat’ symbols mean ‘double-centred’; the ‘bar’ symbols mean ‘mean’</em></p>
<ol start="3">
<li>With the two double-centered matrices, we can calculate the square of the distance covariance by taking the average of each element in <em>X</em> multiplied by its corresponding element in <em>Y</em>.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*N26vQ0n3EepKZWO2T85fWw.png" alt="Image" width="800" height="150" loading="lazy"></p>
<ol start="4">
<li>Now, we can use a similar approach to find the “distance variance”. Remember — the covariance of two identical vectors is equivalent to their variance. Therefore, the squared distance variance can be described as below:</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ld3Be-dShnc2GF6vDKbFAA.png" alt="Image" width="800" height="93" loading="lazy"></p>
<ol start="5">
<li>Finally, we have all the pieces to calculate the distance correlation. Remember that the (distance) standard deviation is equal to the square-root of the (distance) variance.</li>
</ol>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*yVRBk0RhkIO-cs6-WDKgQQ.png" alt="Image" width="800" height="148" loading="lazy"></p>
<p>If you prefer to work through code instead of math notation (after all, there is a reason people tend to write software in one and not the other…), then check out the R implementation below:</p>
<pre><code class="lang-r">set.seed(<span class="hljs-number">1234</span>)

doubleCenter &lt;- <span class="hljs-keyword">function</span>(x){
  centered &lt;- x
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:dim(x)[<span class="hljs-number">1</span>]){
    <span class="hljs-keyword">for</span>(j <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:dim(x)[<span class="hljs-number">2</span>]){
      centered[i,j] &lt;- x[i,j] - mean(x[i,]) - mean(x[,j]) + mean(x)
      }
    }
  <span class="hljs-keyword">return</span>(centered)
}

distanceCovariance &lt;- <span class="hljs-keyword">function</span>(x,y){
  N &lt;- length(x)
  distX &lt;- as.matrix(dist(x))
  distY &lt;- as.matrix(dist(y))
  centeredX &lt;- doubleCenter(distX)
  centeredY &lt;- doubleCenter(distY)
  calc &lt;- sum(centeredX * centeredY)
  <span class="hljs-keyword">return</span>(sqrt(calc/(N^<span class="hljs-number">2</span>)))
 }

distanceVariance &lt;- <span class="hljs-keyword">function</span>(x){
  <span class="hljs-keyword">return</span>(distanceCovariance(x,x))
}
distanceCorrelation &lt;- <span class="hljs-keyword">function</span>(x,y){
  cov &lt;- distanceCovariance(x,y)
  sd &lt;- sqrt(distanceVariance(x)*distanceVariance(y))
  <span class="hljs-keyword">return</span>(cov/sd)
}

<span class="hljs-comment"># Compare with Pearson's r</span>
x &lt;- -<span class="hljs-number">10</span>:<span class="hljs-number">10</span>
y &lt;- x^<span class="hljs-number">2</span> + rnorm(<span class="hljs-number">21</span>,<span class="hljs-number">0</span>,<span class="hljs-number">10</span>)
cor(x,y) <span class="hljs-comment"># --&gt; 0.057</span>
distanceCorrelation(x,y) <span class="hljs-comment"># --&gt; 0.509</span>
</code></pre>
<p>The distance correlation between any two variables is bound between zero and one. Zero implies the variables are independent, whereas a score closer to one indicates a dependent relationship.</p>
<p>If you’d rather not write your own distance correlation methods from scratch, you can install R’s <a target="_blank" href="https://cran.r-project.org/web/packages/energy/index.html"><em>energy</em> package</a>, written by very researchers who devised the method. The methods available in this package call functions written in C, giving a great speed advantage.</p>
<h4 id="heading-physical-interpretation">Physical interpretation</h4>
<p>One of the more surprising results relating to the formulation of distance correlation is that it bears an exact equivalence to Brownian correlation.</p>
<p>Brownian correlation refers to the independence (or dependence) of two Brownian processes. Brownian processes that are dependent will show a tendency to ‘follow’ each other.</p>
<p>A simple metaphor to help grasp the concept of distance correlation is to picture a fleet of paper boats floating on the surface of a lake.</p>
<p>If there is no prevailing wind direction, then each boat will drift about at random — in a way that’s (kind of) analogous to Brownian motion.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LdPHshlMahEF6fL45wQiLA.gif" alt="Image" width="800" height="499" loading="lazy">
<em>Boats drifting under no prevailing wind</em></p>
<p>If there is a prevailing wind, then the direction the boats drift in will be dependent upon the strength of the wind. The stronger the wind, the stronger the dependence.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*gq7Q99iE_0IJt6H8I66pGA.gif" alt="Image" width="800" height="500" loading="lazy">
<em>Under a prevailing wind, the boats will tend to drift in the same direction</em></p>
<p>In a comparable way, uncorrelated variables can be thought of as boats drifting without a prevailing wind. Correlated variables can be thought of as boats drifting under the influence of a prevailing wind. In this metaphor, the wind represents the strength of the relationship between the two variables.</p>
<p>If we allow the prevailing wind direction to vary at different points on the lake, then we can bring a notion of non-linearity into the analogy. Distance correlation uses the distances between the ‘boats’ to infer the strength of the prevailing wind.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*0WWn2l0UKWFQjlW3Zp36mA.gif" alt="Image" width="800" height="499" loading="lazy"></p>
<h4 id="heading-confidence-intervals">Confidence Intervals?</h4>
<p>Confidence intervals can be established for a distance correlation estimate using a ‘resampling’ technique. A simple example is <strong>bootstrap resampling.</strong></p>
<p>This is a neat statistical trick that requires us to ‘reconstruct’ the data by randomly sampling (with replacement) from the original data set. This is repeated many times (e.g., 1000), and each time the statistic of interest is calculated.</p>
<p>This will produce a range of different estimates for the statistic we’re interested in. We can use these to estimate the upper and lower bounds for a given level of confidence.</p>
<p>Check out the R code below for a simple bootstrap function:</p>
<pre><code class="lang-r">set.seed(<span class="hljs-number">1234</span>)

bootstrap &lt;- <span class="hljs-keyword">function</span>(x,y,reps,alpha){
  estimates &lt;- c()
  original &lt;- data.frame(x,y)
  N &lt;- dim(original)[<span class="hljs-number">1</span>]
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:reps){
    S &lt;- original[sample(<span class="hljs-number">1</span>:N, N, replace = <span class="hljs-literal">TRUE</span>),]
    estimates &lt;- append(estimates, distanceCorrelation(S$x, S$y))
  }
  u &lt;- alpha/<span class="hljs-number">2</span> ; l &lt;- <span class="hljs-number">1</span>-u
  interval &lt;- quantile(estimates, c(l, u))
  <span class="hljs-keyword">return</span>(<span class="hljs-number">2</span>*(dcor(x,y)) - as.numeric(interval[<span class="hljs-number">1</span>:<span class="hljs-number">2</span>]))
}

<span class="hljs-comment"># Use with 1000 reps and threshold alpha = 0.05</span>
x &lt;- -<span class="hljs-number">10</span>:<span class="hljs-number">10</span>
y &lt;- x^<span class="hljs-number">2</span> + rnorm(<span class="hljs-number">21</span>,<span class="hljs-number">0</span>,<span class="hljs-number">10</span>)
bootstrap(x,y,<span class="hljs-number">1000</span>,<span class="hljs-number">0.05</span>) <span class="hljs-comment"># --&gt; 0.237 to 0.546</span>
</code></pre>
<p>If you want to establish statistical significance, there is another resampling trick available, called a ‘permutation test’.</p>
<p>This is slightly different to the bootstrap method defined above. Here, we keep one vector constant and ‘shuffle’ the other by resampling. This approximates the null hypothesis — that there is no dependency between the variables.</p>
<p>The ‘shuffled’ variable is then used to calculate the distance correlation between it and the constant variable. This is done many times, and the distribution of outcomes is compared against the actual distance correlation (obtained from the unshuffled data).</p>
<p>The proportion of ‘shuffled’ outcomes greater than or equal to the ‘real’ outcome is then taken as a p-value, which can be compared to a given significance threshold (e.g., 0.05).</p>
<p>Check out the code to see how this works:</p>
<pre><code class="lang-r">permutationTest &lt;- <span class="hljs-keyword">function</span>(x,y,reps){
  estimates &lt;- c()
  observed &lt;- distanceCorrelation(x,y)
  N &lt;- length(x)
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:reps){
    y_i &lt;- sample(y, length(y), replace = <span class="hljs-literal">T</span>)
    estimates &lt;- append(estimates, distanceCorrelation(x, y_i))
  }
  p_value &lt;- mean(estimates &gt;= observed)
  <span class="hljs-keyword">return</span>(p_value)
}

<span class="hljs-comment"># Use with 1000 reps</span>
x &lt;- -<span class="hljs-number">10</span>:<span class="hljs-number">10</span>
y &lt;- x^<span class="hljs-number">2</span> + rnorm(<span class="hljs-number">21</span>,<span class="hljs-number">0</span>,<span class="hljs-number">10</span>)
permutationTest(x,y,<span class="hljs-number">1000</span>) <span class="hljs-comment"># --&gt; 0.036</span>
</code></pre>
<h3 id="heading-maximal-information-coefficient">Maximal Information Coefficient</h3>
<h4 id="heading-what-is-it-2">What is it?</h4>
<p>The Maximal Information Coefficient (MIC) is a recent method for detecting non-linear dependencies between variables, <a target="_blank" href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3325791/">devised in 2011</a>. The algorithm used to calculate MIC applies concepts from information theory and probability to continuous data.</p>
<h4 id="heading-diving-in">Diving in…</h4>
<p>Information theory is a fascinating field within mathematics that was pioneered by <a target="_blank" href="https://www.scientificamerican.com/article/claude-e-shannon-founder/">Claude Shannon</a> in the mid-twentieth century.</p>
<p>A key concept is entropy — a measure of the uncertainty in a given probability distribution. A probability distribution describes the probabilities of a given set of outcomes associated with a particular event.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*b-Blth7fVwFsmzmn10JB9Q.png" alt="Image" width="800" height="166" loading="lazy">
<em>Entropy of a probability distribution is minus “the sum of the probability of each outcome, multiplied by the logarithm of itself”</em></p>
<p>To understand how this works, compare the two probability distributions below:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*9lr_1lXForCox0IodVjkug.png" alt="Image" width="800" height="242" loading="lazy">
<em>Possible outcomes are on the X-axis; their respective probabilities are on the Y-axis</em></p>
<p>On the left is that of a fair six-sided dice, and on the right is the distribution of a not-so-fair six-sided dice.</p>
<p>Intuitively, which would you expect to have the higher entropy? For which dice is the outcome the least certain? Let’s calculate the entropy and see what the answer turns out to be.</p>
<pre><code class="lang-r">entropy &lt;- <span class="hljs-keyword">function</span>(x){
  pr &lt;- prop.table(table(x))
  H &lt;- sum(pr * log(pr,<span class="hljs-number">2</span>))
  <span class="hljs-keyword">return</span>(-H)
}

dice1 &lt;- <span class="hljs-number">1</span>:<span class="hljs-number">6</span>
dice2 &lt;- c(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>:<span class="hljs-number">6</span>)
entropy(dice1) <span class="hljs-comment"># --&gt; 2.585</span>
entropy(dice2) <span class="hljs-comment"># --&gt; 2.281</span>
</code></pre>
<p>As you may have expected, the fairer dice has the higher entropy.</p>
<p>That is because each outcome is as likely as any other, so we cannot know in advance which to favour.</p>
<p>The unfair dice gives us more information — some outcomes are much more likely than others — so there is less uncertainty about the outcome.</p>
<p>By that reasoning, we can see that entropy will be highest when each outcome is equally likely. This type of probability distribution is called a ‘uniform’ distribution.</p>
<p>Cross-entropy is an extension to the concept of entropy, that takes into account a second probability distribution.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*yLJx7NsZUw8SuiklISB3Tg.png" alt="Image" width="800" height="176" loading="lazy"></p>
<pre><code class="lang-r">crossEntropy &lt;- <span class="hljs-keyword">function</span>(x,y){
  prX &lt;- prop.table(table(x))
  prY &lt;- prop.table(table(y))
  H &lt;- sum(prX * log(prY,<span class="hljs-number">2</span>))
  <span class="hljs-keyword">return</span>(-H)
}
</code></pre>
<p>This has the property that the cross-entropy between two identical probability distributions is equal to their individual entropy. When considering two non-identical probability distributions, there will be a difference between their cross-entropy and their individual entropies.</p>
<p>This difference, or ‘divergence’, can be quantified by calculating their <strong>Kullback-Leibler divergence</strong>, or KL-divergence.</p>
<p>The KL-divergence of two probability distributions <em>X</em> and <em>Y</em> is:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*JtGt6d9fT9cEOIjFROvlDw.png" alt="Image" width="800" height="132" loading="lazy">
<em>KL-divergence of probability distributions X and Y equals their cross-entropy, minus the entropy of X</em></p>
<p>The minimum value of the KL-divergence between two distributions is zero. This only happens when the distributions are identical.</p>
<pre><code class="lang-r">KL_divergence &lt;- <span class="hljs-keyword">function</span>(x,y){
  kl &lt;- crossEntropy(x,y) - entropy(x)
  <span class="hljs-keyword">return</span>(kl)
}
</code></pre>
<p>One use for KL-divergence in the context of discovering correlations is to calculate the Mutual Information (MI) of two variables.</p>
<p>Mutual Information can be defined as “the KL-divergence between the joint and marginal distributions of two random variables”. If these are identical, MI will equal zero. If they are at all different, then MI will be a positive number. The more different the joint and marginal distributions are, the higher the MI.</p>
<p>To understand this better, let’s take a moment to revisit some probability concepts.</p>
<p>The joint distribution of variables <em>X</em> and <em>Y</em> is simply the probability of them co-occurring. For instance, if you flipped two coins X and Y, their joint distribution would reflect the probability of each observed outcome. Say you flip the coins 100 times, and get the result “heads, heads” 40 times. The joint distribution would reflect this.</p>
<p>P(X=H, Y=H) = 40/100 = 0.4</p>
<pre><code class="lang-r">jointDist &lt;- <span class="hljs-keyword">function</span>(x,y){
  N &lt;- length(x)
  u &lt;- unique(append(x,y))
  joint &lt;- c()
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> u){
    <span class="hljs-keyword">for</span>(j <span class="hljs-keyword">in</span> u){
      f &lt;- x[paste0(x,y) == paste0(i,j)]
      joint &lt;- append(joint, length(f)/N)
    }
  }
  <span class="hljs-keyword">return</span>(joint)
}
</code></pre>
<p>The marginal distribution is the probability distribution of one variable in the absence of any information about the other. The product of two marginal distributions gives the probability of two events’ co-occurrence under the assumption of independence. </p>
<p>For the coin flipping example, say both coins produce 50 heads and 50 tails. Their marginal distributions would reflect this.</p>
<p>P(X=H) = 50/100 = 0.5 ; P(Y=H) = 50/100 = 0.5</p>
<p>P(X=H) × P(Y=H) = 0.5 × 0.5 = 0.25</p>
<pre><code class="lang-r">marginalProduct &lt;- <span class="hljs-keyword">function</span>(x,y){
  N &lt;- length(x)
  u &lt;- unique(append(x,y))
  marginal &lt;- c()
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> u){
    <span class="hljs-keyword">for</span>(j <span class="hljs-keyword">in</span> u){
      fX &lt;- length(x[x == i]) / N
      fY &lt;- length(y[y == j]) / N 
      marginal &lt;- append(marginal, fX * fY)
    }
  }
  <span class="hljs-keyword">return</span>(marginal)
}
</code></pre>
<p>Returning to the coin flipping example, the product of the marginal distributions will give the probability of observing each outcome if the two coins are independent, while the joint distribution will give the probability of each outcome, as actually observed.</p>
<p>If the coins genuinely are independent, then the joint distribution should be (approximately) identical to the product of the marginal distributions. If they are in some way dependent, then there will be a divergence.</p>
<p>In the example, P(X=H,Y=H) &gt; P(X=H) × P(Y=H). This suggests the coins both land on heads more often than would be expected by chance.</p>
<p>The bigger the divergence between the joint and marginal product distributions, the more likely it is the events are dependent in some way. The measure of this divergence is defined by the Mutual Information of the two variables.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*X6taYiFid97RryShibC0EA.png" alt="Image" width="800" height="119" loading="lazy">
<em>The Mutual Information of X and Y equals “the KL divergence of their joint distribution, and the product of their marginal distributions”</em></p>
<pre><code class="lang-r">mutualInfo &lt;- <span class="hljs-keyword">function</span>(x,y){
  joint &lt;- jointDist(x,y)
  marginal &lt;- marginalProduct(x,y)
  Hjm &lt;- - sum(joint[marginal &gt; <span class="hljs-number">0</span>] * log(marginal[marginal &gt; <span class="hljs-number">0</span>],<span class="hljs-number">2</span>))
  Hj &lt;- - sum(joint[joint &gt; <span class="hljs-number">0</span>] * log(joint[joint &gt; <span class="hljs-number">0</span>],<span class="hljs-number">2</span>))
  <span class="hljs-keyword">return</span>(Hjm - Hj)
}
</code></pre>
<p>A major assumption here is that we are working with discrete probability distributions. How can we apply these concepts to continuous data?</p>
<h4 id="heading-binning">Binning</h4>
<p>One approach is to quantize the data (make the variables discrete). This is achieved by binning (assigning data points to discrete categories).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*2sGH19Kz_6ARGjJqiunfBQ.png" alt="Image" width="800" height="312" loading="lazy"></p>
<p>The key issue now is deciding how many bins to use. Luckily, the original paper on the Maximal Information Coefficient provides a suggestion: try most of them!</p>
<p>That is to say, try differing numbers of bins and see which produces the greatest result of Mutual Information between the variables. This raises two challenges, though:</p>
<ol>
<li>How many bins to try? Technically, you could quantize a variable into any number of bins, simply by making the bin size forever smaller.</li>
<li>Mutual Information is sensitive to the number of bins used. How do you fairly compare MI between different numbers of bins?</li>
</ol>
<p>The first challenge means it is technically impossible to try every possible number of bins. However, the authors of the paper offer a <strong>heuristic</strong> solution (that is, a solution which is not ‘guaranteed perfect’, but is a pretty good approximation). They also suggest an upper limit on the number of bins to try.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Jo83vdT1qLzkMJrPygGT3Q.png" alt="Image" width="800" height="145" loading="lazy">
<em>The maximum number of bins to try is determined by the sample size, N</em></p>
<p>As for fairly comparing MI values between different binning schemes, there’s a simple fix… normalize it! This can be done by dividing each MI score by the maximum it could theoretically take for that particular combination of bins.</p>
<p>The binning combination that produces the highest normalized MI overall is the one to use.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XCncBPn0hPhpqGG8FdD-MQ.png" alt="Image" width="800" height="152" loading="lazy">
<em>Mutual Information can be normalized by dividing by the logarithm of the smallest number of bins</em></p>
<p>The highest normalized MI is then reported as the Maximal Information Coefficient (or ‘MIC’) for those two variables. Let’s check out some code that will estimate the MIC of two continuous variables.</p>
<pre><code class="lang-r">MIC &lt;- <span class="hljs-keyword">function</span>(x,y){
  N &lt;- length(x)
  maxBins &lt;- ceiling(N ** <span class="hljs-number">0.6</span>)
  MI &lt;- c()
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>:maxBins) {
    <span class="hljs-keyword">for</span> (j <span class="hljs-keyword">in</span> <span class="hljs-number">2</span>:maxBins){
      <span class="hljs-keyword">if</span>(i * j &gt; maxBins){
        <span class="hljs-keyword">next</span>
      }
      Xbins &lt;- i; Ybins &lt;- j
      binnedX &lt;-cut(x, breaks=Xbins, labels = <span class="hljs-number">1</span>:Xbins)
      binnedY &lt;-cut(y, breaks=Ybins, labels = <span class="hljs-number">1</span>:Ybins)
      MI_estimate &lt;- mutualInfo(binnedX,binnedY)
      MI_normalized &lt;- MI_estimate / log(min(Xbins,Ybins),<span class="hljs-number">2</span>)
      MI &lt;- append(MI, MI_normalized)
    }
  }
  <span class="hljs-keyword">return</span>(max(MI))
}

x &lt;- runif(<span class="hljs-number">100</span>,-<span class="hljs-number">10</span>,<span class="hljs-number">10</span>)
y &lt;- x**<span class="hljs-number">2</span> + rnorm(<span class="hljs-number">100</span>,<span class="hljs-number">0</span>,<span class="hljs-number">10</span>)
MIC(x,y) <span class="hljs-comment"># --&gt; 0.751</span>
</code></pre>
<p>The above code is a simplification of the method outlined in the original paper. A more faithful implementation of the algorithm is available in the <a target="_blank" href="https://cran.r-project.org/web/packages/minerva/index.html">R package <em>minerva</em></a>. In Python, you can use the <a target="_blank" href="https://minepy.readthedocs.io/en/latest/"><em>minepy</em> module</a>.</p>
<p>MIC is capable of picking out all kinds of linear and non-linear relationships, and has found use in a range of different applications. It is bound between 0 and 1, with higher values indicating greater dependence.</p>
<h4 id="heading-confidence-intervals-1">Confidence Intervals?</h4>
<p>To establish confidence bounds on an estimate of MIC, you can simply use a bootstrapping technique like the one we looked at earlier.</p>
<p>To generalize the bootstrap function, we can take advantage of R’s functional programming capabilities, by passing the technique we want to use as an argument.</p>
<pre><code class="lang-r">bootstrap &lt;- <span class="hljs-keyword">function</span>(x,y,func,reps,alpha){
  estimates &lt;- c()
  original &lt;- data.frame(x,y)
  N &lt;- dim(original)[<span class="hljs-number">1</span>]
  <span class="hljs-keyword">for</span>(i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>:reps){
    S &lt;- original[sample(<span class="hljs-number">1</span>:N, N, replace = <span class="hljs-literal">TRUE</span>),]
    estimates &lt;- append(estimates, func(S$x, S$y))
  }
  l &lt;- alpha/<span class="hljs-number">2</span> ; u &lt;- <span class="hljs-number">1</span> - l
  interval &lt;- quantile(estimates, c(u, l))
  <span class="hljs-keyword">return</span>(<span class="hljs-number">2</span>*(func(x,y)) - as.numeric(interval[<span class="hljs-number">1</span>:<span class="hljs-number">2</span>]))
}

bootstrap(x,y,MIC,<span class="hljs-number">100</span>,<span class="hljs-number">0.05</span>) <span class="hljs-comment"># --&gt; 0.594 to 0.88</span>
</code></pre>
<h3 id="heading-summary">Summary</h3>
<p>To conclude this tour of correlation, let’s test each different method against a range of artificially generated data. The code for these examples can be found <a target="_blank" href="https://gist.github.com/anonymous/fabecccf33f9c3feb568384f626a2c07">here</a>.</p>
<h4 id="heading-noise">Noise</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*aEUhq3mlWtiynokMapcAhA.png" alt="Image" width="800" height="325" loading="lazy"></p>
<pre><code class="lang-r">set.seed(<span class="hljs-number">123</span>)

<span class="hljs-comment"># Noise</span>
x0 &lt;- rnorm(<span class="hljs-number">100</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>)
y0 &lt;- rnorm(<span class="hljs-number">100</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>)
plot(y0~x0, pch = <span class="hljs-number">18</span>)

cor(x0,y0)
distanceCorrelation(x0,y0)
MIC(x0,y0)
</code></pre>
<ul>
<li>Pearson’s <em>r</em> = - 0.05</li>
<li>Distance Correlation = 0.157</li>
<li>MIC = 0.097</li>
</ul>
<h4 id="heading-simple-linear">Simple linear</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*YQBdb395rjfBZfEE5eBm4A.png" alt="Image" width="800" height="327" loading="lazy"></p>
<pre><code class="lang-r"><span class="hljs-comment"># Simple linear relationship</span>
x1 &lt;- -<span class="hljs-number">20</span>:<span class="hljs-number">20</span>
y1 &lt;- x1 + rnorm(<span class="hljs-number">41</span>,<span class="hljs-number">0</span>,<span class="hljs-number">4</span>)
plot(y1~x1, pch =<span class="hljs-number">18</span>)

cor(x1,y1)
distanceCorrelation(x1,y1)
MIC(x1,y1)
</code></pre>
<ul>
<li>Pearson’s <em>r</em> =+0.95</li>
<li>Distance Correlation = 0.95</li>
<li>MIC = 0.89</li>
</ul>
<h4 id="heading-simple-quadratic">Simple quadratic</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*pd4YYdHAH9XojT8LspOswg.png" alt="Image" width="800" height="322" loading="lazy"></p>
<pre><code class="lang-r"><span class="hljs-comment"># y ~ x**2</span>
x2 &lt;- -<span class="hljs-number">20</span>:<span class="hljs-number">20</span>
y2 &lt;- x2**<span class="hljs-number">2</span> + rnorm(<span class="hljs-number">41</span>,<span class="hljs-number">0</span>,<span class="hljs-number">40</span>)
plot(y2~x2, pch = <span class="hljs-number">18</span>)

cor(x2,y2)
distanceCorrelation(x2,y2)
MIC(x2,y2)
</code></pre>
<ul>
<li>Pearson’s <em>r</em> =+0.003</li>
<li>Distance Correlation = 0.474</li>
<li>MIC = 0.594</li>
</ul>
<h4 id="heading-trigonometric">Trigonometric</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*21DeF8IUBSXWNeeqzGXTRg.png" alt="Image" width="800" height="339" loading="lazy"></p>
<pre><code class="lang-r"><span class="hljs-comment"># Cosine</span>
x3 &lt;- -<span class="hljs-number">20</span>:<span class="hljs-number">20</span>
y3 &lt;- cos(x3/<span class="hljs-number">4</span>) + rnorm(<span class="hljs-number">41</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0.2</span>)
plot(y3~x3, type=<span class="hljs-string">'p'</span>, pch=<span class="hljs-number">18</span>)

cor(x3,y3)
distanceCorrelation(x3,y3)
MIC(x3,y3)
</code></pre>
<ul>
<li>Pearson’s <em>r</em> = - 0.035</li>
<li>Distance Correlation = 0.382</li>
<li>MIC = 0.484</li>
</ul>
<h4 id="heading-circle">Circle</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*XqNA4leGe7r68B0xxclIVA.png" alt="Image" width="800" height="440" loading="lazy"></p>
<pre><code class="lang-r"><span class="hljs-comment"># Circle</span>

n &lt;- <span class="hljs-number">50</span>
theta &lt;- runif (n, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>*pi)
x4 &lt;- append(cos(theta), cos(theta))
y4 &lt;- append(sin(theta), -sin(theta))
plot(x4,y4, pch=<span class="hljs-number">18</span>)

cor(x4,y4)
distanceCorrelation(x4,y4)
MIC(x4,y4)
</code></pre>
<ul>
<li>Pearson’s <em>r</em> &lt; 0.001</li>
<li>Distance Correlation = 0.234</li>
<li>MIC = 0.218</li>
</ul>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How you can use linear regression models to predict quadratic, root, and polynomial functions ]]>
                </title>
                <description>
                    <![CDATA[ By Björn Hartmann When reading articles about machine learning, I often suspect that authors misunderstand the term “linear model.” Many authors suggest that linear models can only be applied if data can be described with a line. But this is way too ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-how-to-improve-your-linear-models-8294bfa8a731/</link>
                <guid isPermaLink="false">66c359b2f83dfae169b2c00b</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 11 Oct 2017 16:00:41 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*GsSExG8KXYBd6rk7assRTQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Björn Hartmann</p>
<p>When reading articles about machine learning, I often suspect that authors misunderstand the term “linear model.” Many authors suggest that linear models can only be applied if data can be described with a line. But this is way too restrictive.</p>
<p>Linear models <strong>assume the functional form is linear — not the relationship between your variables</strong>.</p>
<p>I’ll show you how you can improve your linear regressions with quadratic, root, and exponential functions.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3hDIpUpiqmEqht4LpuzcXCnSIvUHGAUlruxI" alt="Image" width="800" height="215" loading="lazy"></p>
<h3 id="heading-so-whats-the-functional-form">So what’s the functional form?</h3>
<p>The functional form is the <strong>equation you want to estimate</strong>.</p>
<p>Let us start with an example and think about how we could describe salaries of data scientists. Suppose an average data scientist (<code>i</code>) receives an entry-level salary (<code>entry_level_salary</code>) plus a bonus for each year of his experience (<code>experience_i</code>).</p>
<p>Thus, his salary (<code>salary_i</code>) is given by the following functional form:</p>
<pre><code>salary_i = entry_level_salary + beta_1 * experience_i
</code></pre><p>Now, we can interpret the coefficient <code>beta_1</code> as the bonus for each year of experience. And with this coefficient we can start making predictions by just knowing the level of experience.</p>
<p>As your machine learning model takes care of the coefficient <code>beta_1</code> , all you need to enter in R or any other software is:</p>
<pre><code>model_1 &lt;- lm(salary ~ entry_level_salary + experience)
</code></pre><p>Linearity in the functional form requires that we sum up each determinant on the right-hand side of the equation.</p>
<p>Imagine we are right with our assumptions. Each point indicates one data scientist with his level of experience and salary. Finally, the red line is our predictions.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wQDyE0LxhC8MjRfFhYJUckvRjMxaAf-761dG" alt="Image" width="520" height="450" loading="lazy"></p>
<p>Many aspiring data scientists already run similar predictions. But often that is all they do with linear models…</p>
<h3 id="heading-how-to-estimate-quadratic-models">How to estimate quadratic models?</h3>
<p>When we want to estimate a quadratic model, we cannot type in something like this:</p>
<pre><code>model_2 &lt;- lm(salary ~ entry_level_salary + experience^<span class="hljs-number">2</span>)
</code></pre><pre><code>&gt;&gt; This will reject an error message
</code></pre><p>Most of these functions do not expect that they have to transform your input variables. As a result, they reject an error message if you try. Furthermore, you do not have a sum at the right-hand side of the equation anymore.</p>
<p><strong>Note:</strong> You need to compute <code>experience^²</code> before adding it into your model. Thus, you will run:</p>
<pre><code># First, compute the square values <span class="hljs-keyword">of</span> experienceexperience_2 &lt;- experience^<span class="hljs-number">2</span>
</code></pre><pre><code># Then add them into your regressionmodel_2 &lt;- lm(salary ~ entry_level_salary + experience_2)
</code></pre><p>In return, you get a nice quadratic function:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/2MNxj09K-gnrnxKAJspCA84cUFOQB1CSbCBA" alt="Image" width="520" height="450" loading="lazy"></p>
<h3 id="heading-estimate-root-functions-with-linear-models">Estimate root functions with linear models</h3>
<p>Often we observe values that rise fast in the beginning and align to certain level afterwards. Let us modify our example and estimate a typical learning curve.</p>
<p>In the beginning a learning curve tends to be very steep and slows down after some years.</p>
<p>There is one function that features such a trend, the <code>root</code> function. So we use the <code>square root</code> of <code>experience</code> to capture this relationship:</p>
<pre><code># First, compute the square root values <span class="hljs-keyword">of</span> experiencesqrt_experience &lt;- sqrt(experience)
</code></pre><pre><code># Then add them into your regressionmodel_3 &lt;- lm(knowledge ~ sqrt_experience)
</code></pre><p>Again, make sure you compute the square root before you add it to your model:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ZKh8gvc9V8Wz-9Hht1PJHA67-n6PJh6cP6Mm" alt="Image" width="520" height="450" loading="lazy"></p>
<p>Or you might want to use the logarithmic function as it describes a similar trend. But its’ values are negative between zero and one. So make sure this is not a problem for you and your data.</p>
<h3 id="heading-mastering-linear-models">Mastering linear models</h3>
<p>Finally, you can even estimate polynomial functions with higher orders or exponential functions. All you need to do is to compute all variables before you add them into your linear model:</p>
<pre><code># First, compute polynomialsexperience_2 &lt;- experience^<span class="hljs-number">2</span>experience_3 &lt;- experience^<span class="hljs-number">3</span>
</code></pre><pre><code># Then add them into your regressionmodel_4 &lt;- lm(salary ~ experience + experience_2 + experience_3)
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/91UHlbibDwztx9AAcMQMPFqKA9Ub5zLpekOu" alt="Image" width="520" height="450" loading="lazy"></p>
<h3 id="heading-two-cases-where-you-should-use-other-models">Two cases where you should use other models</h3>
<p>Although linear models can be applied to many cases, there are limitations. The most popular can be divided into two categories:</p>
<h4 id="heading-1-probabilities">1. Probabilities:</h4>
<p>If you want to estimate the probability of an event, you better use Probit, Logit or Tobit models. When estimating probabilities you use distributions that linear functions cannot capture. Depending on the distribution you assume, you should choose between the Probit, Logit or Tobit model.</p>
<h4 id="heading-2-count-variables">2. Count variables</h4>
<p>Finally, when estimating a count variable you want to use a Poisson model. Count variables are variable that can only be integers such as <code>1, 2, 3, 4</code>.</p>
<p>For example count the number of children, the number of purchases a customer makes or the number of accidents in a region.</p>
<h3 id="heading-what-to-take-away-from-this-article">What to take away from this article</h3>
<p>There are two things I want you to remember:</p>
<ol>
<li>Improve your linear models and try quadratic, root or polynomial functions.</li>
<li>Always transform your data <strong>before</strong> you add them to your regression.</li>
</ol>
<p>I uploaded the R code for all examples on <a target="_blank" href="https://github.com/bjoernhartmann/examples_linear_models">GitHub</a>. Feel free to download them, play with them, or share them with your friends and colleagues.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Er55BWHmZF-gxXl1HofpZX2znuPqRM7eIf88" alt="Image" width="700" height="235" loading="lazy"></p>
<p>If you have any questions, write a comment below or <a target="_blank" href="https://www.bjoern-hartmann.de/?utm_source=medium&amp;utm_medium=link&amp;utm_campaign=Linear_Models&amp;utm_term=Linear_Models">contact me</a>. I appreciate your feedback.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
