<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>dplyr on R Views</title>
    <link>https://rviews.rstudio.com/tags/dplyr/</link>
    <description>Recent content in dplyr on R Views</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 06 Mar 2019 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://rviews.rstudio.com/tags/dplyr/" rel="self" type="application/rss+xml" />
    
    
    
    
    <item>
      <title>Graph analysis using the tidyverse</title>
      <link>https://rviews.rstudio.com/2019/03/06/intro-to-graph-analysis/</link>
      <pubDate>Wed, 06 Mar 2019 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2019/03/06/intro-to-graph-analysis/</guid>
      <description>
        


&lt;p&gt;It is because I am not a graph analysis expert that I thought it important to write this article. For someone who thinks in terms of single rectangular data sets, it is a bit of a mental leap to understand how to apply &lt;em&gt;tidy&lt;/em&gt; principles to a more robust object, such as a graph table. Thankfully, there are two packages that make this work much easier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/thomasp85/tidygraph&#34;&gt;&lt;code&gt;tidygraph&lt;/code&gt;&lt;/a&gt; - Provides a way for &lt;code&gt;dplyr&lt;/code&gt; to interact with graphs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/thomasp85/ggraph&#34;&gt;&lt;code&gt;ggraph&lt;/code&gt;&lt;/a&gt; - Extension to &lt;code&gt;ggplot2&lt;/code&gt; for graph analysis&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;quick-intro&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Quick intro&lt;/h3&gt;
&lt;p&gt;Simply put, graph theory studies relationships between objects in a group. Visually, we can think of a graph as a series of interconnected circles, each representing a member of a group, such as people in a Social Network. Lines drawn between the circles represent a relationship between the members, such as friendships in a Social Network. Graph analysis helps with figuring out things such as the influence of a certain member, or how many friends are in between two members. A more formal definition and detailed explanation of Graph Theory can be found in &lt;a href=&#34;https://en.wikipedia.org/wiki/Graph_theory&#34;&gt;Wikipedia here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Using an example, this article will introduce concepts of graph analysis work, and how &lt;code&gt;tidyverse&lt;/code&gt; and &lt;code&gt;tidyverse&lt;/code&gt;-adjacent tools can be used for such analysis.&lt;/p&gt;
&lt;div id=&#34;data-source&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Data source&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/rfordatascience/tidytuesday&#34;&gt;tidytuesday&lt;/a&gt; weekly project encourages new and experienced users to use the &lt;code&gt;tidyverse&lt;/code&gt; tools to analyze data sets that change every week. I have been using that opportunity to lean new tools and techniques. One of the most recent data sets relates to French trains; it contains aggregate daily total trips per connecting stations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(readr)

url &amp;lt;- &amp;quot;https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-02-26/small_trains.csv&amp;quot;
small_trains &amp;lt;- read_csv(url)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(small_trains)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 13
##    year month service departure_stati… arrival_station journey_time_avg
##   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;            &amp;lt;chr&amp;gt;                      &amp;lt;dbl&amp;gt;
## 1  2017     9 Nation… PARIS EST        METZ                        85.1
## 2  2017     9 Nation… REIMS            PARIS EST                   47.1
## 3  2017     9 Nation… PARIS EST        STRASBOURG                 116. 
## 4  2017     9 Nation… PARIS LYON       AVIGNON TGV                161. 
## 5  2017     9 Nation… PARIS LYON       BELLEGARDE (AI…            164. 
## 6  2017     9 Nation… PARIS LYON       BESANCON FRANC…            129. 
## # … with 7 more variables: total_num_trips &amp;lt;int&amp;gt;,
## #   avg_delay_all_departing &amp;lt;dbl&amp;gt;, avg_delay_all_arriving &amp;lt;dbl&amp;gt;,
## #   num_late_at_departure &amp;lt;int&amp;gt;, num_arriving_late &amp;lt;int&amp;gt;,
## #   delay_cause &amp;lt;chr&amp;gt;, delayed_number &amp;lt;dbl&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;data-preparation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Data Preparation&lt;/h3&gt;
&lt;p&gt;Even though it was meant to analyze delays, I thought it would be interesting to use the data to understand how stations connect with each other. A new summarized data set is created, called &lt;em&gt;routes&lt;/em&gt;, which contains a single entry for each connected station. It also includes the average journey time it takes to go between stations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)

routes &amp;lt;- small_trains %&amp;gt;%
  group_by(departure_station, arrival_station) %&amp;gt;%
  summarise(journey_time = mean(journey_time_avg)) %&amp;gt;%
  ungroup() %&amp;gt;%
  mutate(from = departure_station, 
         to = arrival_station) %&amp;gt;%
  select(from, to, journey_time)

routes&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 130 x 3
##    from                       to                 journey_time
##    &amp;lt;chr&amp;gt;                      &amp;lt;chr&amp;gt;                     &amp;lt;dbl&amp;gt;
##  1 AIX EN PROVENCE TGV        PARIS LYON                186. 
##  2 ANGERS SAINT LAUD          PARIS MONTPARNASSE         97.5
##  3 ANGOULEME                  PARIS MONTPARNASSE        146. 
##  4 ANNECY                     PARIS LYON                225. 
##  5 ARRAS                      PARIS NORD                 52.8
##  6 AVIGNON TGV                PARIS LYON                161. 
##  7 BARCELONA                  PARIS LYON                358. 
##  8 BELLEGARDE (AIN)           PARIS LYON                163. 
##  9 BESANCON FRANCHE COMTE TGV PARIS LYON                131. 
## 10 BORDEAUX ST JEAN           PARIS MONTPARNASSE        186. 
## # … with 120 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next step is to transform the tidy data set, into a graph table. In order to prepare &lt;em&gt;routes&lt;/em&gt; for this transformation, it has to contain two variables specifically named: &lt;em&gt;from&lt;/em&gt; and &lt;em&gt;to&lt;/em&gt;, which are the names that &lt;code&gt;tidygraph&lt;/code&gt; expects to see. Those variables should contain the name of each member (e.g., “AIX EN PROVENCE TGV”), and the relationship (“AIX EN PROVENCE TGV” -&amp;gt; “PARIS LYON”) .&lt;/p&gt;
&lt;p&gt;In graph terminology, a member of the group is called a &lt;strong&gt;node&lt;/strong&gt; (or vertex) in the graph, and a relationship between nodes is called an &lt;strong&gt;edge&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidygraph)

graph_routes &amp;lt;- as_tbl_graph(routes)

graph_routes&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tbl_graph: 59 nodes and 130 edges
## #
## # A directed simple graph with 1 component
## #
## # Node Data: 59 x 1 (active)
##   name               
##   &amp;lt;chr&amp;gt;              
## 1 AIX EN PROVENCE TGV
## 2 ANGERS SAINT LAUD  
## 3 ANGOULEME          
## 4 ANNECY             
## 5 ARRAS              
## 6 AVIGNON TGV        
## # … with 53 more rows
## #
## # Edge Data: 130 x 3
##    from    to journey_time
##   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;        &amp;lt;dbl&amp;gt;
## 1     1    39        186. 
## 2     2    40         97.5
## 3     3    40        146. 
## # … with 127 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;as_tbl_graph()&lt;/code&gt; function splits the &lt;em&gt;routes&lt;/em&gt; table into two:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;p&gt;Node Data - Contains all of the unique values found in the &lt;em&gt;from&lt;/em&gt; and &lt;em&gt;to&lt;/em&gt; variables. In this case, it is a table with a single column containing the names of all of the stations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edge Data - Is a table of all relationships between &lt;em&gt;from&lt;/em&gt; and &lt;em&gt;to&lt;/em&gt;. A peculiarity of &lt;code&gt;tidygraph&lt;/code&gt; is that it uses the row position of the node as the identifier for &lt;em&gt;from&lt;/em&gt; and &lt;em&gt;to&lt;/em&gt;, instead of its original name.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Another interesting thing about &lt;code&gt;tidygraph&lt;/code&gt; is that it allows us to attach more information about the node or edge in an additional column. In this case, &lt;em&gt;journey_time&lt;/em&gt; is not really needed to create the graph table, but it may be needed for the analysis we plan to perform. The &lt;code&gt;as_tbl_graph()&lt;/code&gt; function automatically created the column for us.&lt;/p&gt;
&lt;p&gt;Thinking about &lt;em&gt;graph_routes&lt;/em&gt; as two &lt;code&gt;tibbles&lt;/code&gt; inside a larger table graph, was one of the two major mental breakthroughs I had during this exercise. At that point, it became evident that &lt;code&gt;dplyr&lt;/code&gt; needs a way to know which of the two tables (nodes or edges) to perform the transformations on. In &lt;code&gt;tidygraph&lt;/code&gt;, this is done using the &lt;code&gt;activate()&lt;/code&gt; function. To showcase this, the nodes table will be “activated” in order to add two new string variables derived from &lt;em&gt;name&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(stringr)

graph_routes &amp;lt;- graph_routes %&amp;gt;%
  activate(nodes) %&amp;gt;%
  mutate(
    title = str_to_title(name),
    label = str_replace_all(title, &amp;quot; &amp;quot;, &amp;quot;\n&amp;quot;)
    )

graph_routes&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tbl_graph: 59 nodes and 130 edges
## #
## # A directed simple graph with 1 component
## #
## # Node Data: 59 x 3 (active)
##   name                title               label                   
##   &amp;lt;chr&amp;gt;               &amp;lt;chr&amp;gt;               &amp;lt;chr&amp;gt;                   
## 1 AIX EN PROVENCE TGV Aix En Provence Tgv &amp;quot;Aix\nEn\nProvence\nTgv&amp;quot;
## 2 ANGERS SAINT LAUD   Angers Saint Laud   &amp;quot;Angers\nSaint\nLaud&amp;quot;   
## 3 ANGOULEME           Angouleme           Angouleme               
## 4 ANNECY              Annecy              Annecy                  
## 5 ARRAS               Arras               Arras                   
## 6 AVIGNON TGV         Avignon Tgv         &amp;quot;Avignon\nTgv&amp;quot;          
## # … with 53 more rows
## #
## # Edge Data: 130 x 3
##    from    to journey_time
##   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;        &amp;lt;dbl&amp;gt;
## 1     1    39        186. 
## 2     2    40         97.5
## 3     3    40        146. 
## # … with 127 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It was really impressive how easy it was to manipulate the graph table, because once one of the two tables are activated, all of the changes can be made using &lt;code&gt;tidyverse&lt;/code&gt; tools. The same approach can be used to extract data from the graph table. In this case, a list of all the stations is pulled into a single character vector.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;stations &amp;lt;- graph_routes %&amp;gt;%
  activate(nodes) %&amp;gt;%
  pull(title)

stations&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;Aix En Provence Tgv&amp;quot;            &amp;quot;Angers Saint Laud&amp;quot;             
##  [3] &amp;quot;Angouleme&amp;quot;                      &amp;quot;Annecy&amp;quot;                        
##  [5] &amp;quot;Arras&amp;quot;                          &amp;quot;Avignon Tgv&amp;quot;                   
##  [7] &amp;quot;Barcelona&amp;quot;                      &amp;quot;Bellegarde (Ain)&amp;quot;              
##  [9] &amp;quot;Besancon Franche Comte Tgv&amp;quot;     &amp;quot;Bordeaux St Jean&amp;quot;              
## [11] &amp;quot;Brest&amp;quot;                          &amp;quot;Chambery Challes Les Eaux&amp;quot;     
## [13] &amp;quot;Dijon Ville&amp;quot;                    &amp;quot;Douai&amp;quot;                         
## [15] &amp;quot;Dunkerque&amp;quot;                      &amp;quot;Francfort&amp;quot;                     
## [17] &amp;quot;Geneve&amp;quot;                         &amp;quot;Grenoble&amp;quot;                      
## [19] &amp;quot;Italie&amp;quot;                         &amp;quot;La Rochelle Ville&amp;quot;             
## [21] &amp;quot;Lausanne&amp;quot;                       &amp;quot;Laval&amp;quot;                         
## [23] &amp;quot;Le Creusot Montceau Montchanin&amp;quot; &amp;quot;Le Mans&amp;quot;                       
## [25] &amp;quot;Lille&amp;quot;                          &amp;quot;Lyon Part Dieu&amp;quot;                
## [27] &amp;quot;Macon Loche&amp;quot;                    &amp;quot;Madrid&amp;quot;                        
## [29] &amp;quot;Marne La Vallee&amp;quot;                &amp;quot;Marseille St Charles&amp;quot;          
## [31] &amp;quot;Metz&amp;quot;                           &amp;quot;Montpellier&amp;quot;                   
## [33] &amp;quot;Mulhouse Ville&amp;quot;                 &amp;quot;Nancy&amp;quot;                         
## [35] &amp;quot;Nantes&amp;quot;                         &amp;quot;Nice Ville&amp;quot;                    
## [37] &amp;quot;Nimes&amp;quot;                          &amp;quot;Paris Est&amp;quot;                     
## [39] &amp;quot;Paris Lyon&amp;quot;                     &amp;quot;Paris Montparnasse&amp;quot;            
## [41] &amp;quot;Paris Nord&amp;quot;                     &amp;quot;Paris Vaugirard&amp;quot;               
## [43] &amp;quot;Perpignan&amp;quot;                      &amp;quot;Poitiers&amp;quot;                      
## [45] &amp;quot;Quimper&amp;quot;                        &amp;quot;Reims&amp;quot;                         
## [47] &amp;quot;Rennes&amp;quot;                         &amp;quot;Saint Etienne Chateaucreux&amp;quot;    
## [49] &amp;quot;St Malo&amp;quot;                        &amp;quot;St Pierre Des Corps&amp;quot;           
## [51] &amp;quot;Strasbourg&amp;quot;                     &amp;quot;Stuttgart&amp;quot;                     
## [53] &amp;quot;Toulon&amp;quot;                         &amp;quot;Toulouse Matabiau&amp;quot;             
## [55] &amp;quot;Tourcoing&amp;quot;                      &amp;quot;Tours&amp;quot;                         
## [57] &amp;quot;Valence Alixan Tgv&amp;quot;             &amp;quot;Vannes&amp;quot;                        
## [59] &amp;quot;Zurich&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;visualizing&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Visualizing&lt;/h2&gt;
&lt;p&gt;In graphs, the absolute position of the each node is not as relevant as it is with other kinds of visualizations. A very minimal &lt;code&gt;ggplot2&lt;/code&gt; theme is set to make it easier to view the plotted graph.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

thm &amp;lt;- theme_minimal() +
  theme(
    legend.position = &amp;quot;none&amp;quot;,
     axis.title = element_blank(),
     axis.text = element_blank(),
     panel.grid = element_blank(),
     panel.grid.major = element_blank(),
  ) 

theme_set(thm)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To create the plot, start with &lt;code&gt;ggraph()&lt;/code&gt; instead of &lt;code&gt;ggplot2()&lt;/code&gt;. The &lt;code&gt;ggraph&lt;/code&gt; package contains &lt;code&gt;geoms&lt;/code&gt; that are unique to graph analysis. The package contains &lt;code&gt;geoms&lt;/code&gt; to specifically plot nodes, and other &lt;code&gt;geoms&lt;/code&gt; for edges.&lt;/p&gt;
&lt;p&gt;As a first basic test, the &lt;em&gt;point&lt;/em&gt; &lt;code&gt;geom&lt;/code&gt; will be used, but instead of calling&lt;code&gt;geom_point()&lt;/code&gt;, we call &lt;code&gt;geom_node_point()&lt;/code&gt;. The edges are plotted using &lt;code&gt;geom_edge_diagonal()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggraph) 

graph_routes %&amp;gt;%
  ggraph(layout = &amp;quot;kk&amp;quot;) +
    geom_node_point() +
    geom_edge_diagonal() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2019-02-28-intro-to-graph-analysis_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;To make it easier to see where each station is placed in this plot, the &lt;code&gt;geom_node_text()&lt;/code&gt; is used. Just as with regular &lt;code&gt;geoms&lt;/code&gt; in &lt;code&gt;ggplot2&lt;/code&gt;, other attributes such as &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, and &lt;code&gt;alpha&lt;/code&gt; can be modified.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;graph_routes %&amp;gt;%
  ggraph(layout = &amp;quot;kk&amp;quot;) +
    geom_node_text(aes(label = label, color = name), size = 3) +
    geom_edge_diagonal(color = &amp;quot;gray&amp;quot;, alpha = 0.4) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2019-02-28-intro-to-graph-analysis_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;morphing-time&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Morphing time!&lt;/h2&gt;
&lt;p&gt;The second mental leap was understanding how a graph algorithm is applied. Typically, the output of a model function is a model object, not a data object. With &lt;code&gt;tidygraph&lt;/code&gt;, the process begins and ends with a graph table. The steps are these:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Start with a graph table&lt;/li&gt;
&lt;li&gt;Temporarily transform the graph to comply with the model that is requested (&lt;code&gt;morph()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Add additional transformations to the morphed data using &lt;code&gt;dplyr&lt;/code&gt; (optional)&lt;/li&gt;
&lt;li&gt;Restore the original graph table, but modified to keep the changes made during the morph&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The shortest path algorithm defines the “length” as the number of edges in between two nodes. There may be multiple routes to get from point A to point B, but the algorithm chooses the one with the fewest number of “hops”. The way to call the algorithm is inside the &lt;code&gt;morph()&lt;/code&gt; function. Even though &lt;code&gt;to_shortest_path()&lt;/code&gt; is a function in itself, and it is possible run it without &lt;code&gt;morph()&lt;/code&gt;, it is not meant to be used that way. In the example, the &lt;em&gt;journey_time&lt;/em&gt; is used as &lt;code&gt;weights&lt;/code&gt; to help the algorithm find an optimal route between the &lt;em&gt;Arras&lt;/em&gt; and the &lt;em&gt;Nancy&lt;/em&gt; stations. The print output of the morphed graph will not be like the original graph table.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;from &amp;lt;- which(stations == &amp;quot;Arras&amp;quot;)
to &amp;lt;-  which(stations == &amp;quot;Nancy&amp;quot;)

shortest &amp;lt;- graph_routes %&amp;gt;%
  morph(to_shortest_path, from, to, weights = journey_time)

shortest&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tbl_graph temporarily morphed to a shortest path representation
## # 
## # Original graph is a directed simple graph with 1 component
## # consisting of 59 nodes and 130 edges&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is possible to make more transformations with the use of &lt;code&gt;activate()&lt;/code&gt; and &lt;code&gt;dplyr&lt;/code&gt; functions. The results can be previewed, or committed back to the original R variable using &lt;code&gt;unmorph()&lt;/code&gt;. By default, nodes are active in a morphed graph, so there is no need to set that explicitly.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest %&amp;gt;%
  mutate(selected_node = TRUE) %&amp;gt;%
  unmorph()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tbl_graph: 59 nodes and 130 edges
## #
## # A directed simple graph with 1 component
## #
## # Node Data: 59 x 4 (active)
##   name               title              label                 selected_node
##   &amp;lt;chr&amp;gt;              &amp;lt;chr&amp;gt;              &amp;lt;chr&amp;gt;                 &amp;lt;lgl&amp;gt;        
## 1 AIX EN PROVENCE T… Aix En Provence T… &amp;quot;Aix\nEn\nProvence\n… NA           
## 2 ANGERS SAINT LAUD  Angers Saint Laud  &amp;quot;Angers\nSaint\nLaud&amp;quot; NA           
## 3 ANGOULEME          Angouleme          Angouleme             NA           
## 4 ANNECY             Annecy             Annecy                NA           
## 5 ARRAS              Arras              Arras                 TRUE         
## 6 AVIGNON TGV        Avignon Tgv        &amp;quot;Avignon\nTgv&amp;quot;        NA           
## # … with 53 more rows
## #
## # Edge Data: 130 x 3
##    from    to journey_time
##   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;        &amp;lt;dbl&amp;gt;
## 1     1    39        186. 
## 2     2    40         97.5
## 3     3    40        146. 
## # … with 127 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it was morphed, only the few nodes that make up the connections between the Arras and Nancy stations were selected. A simple &lt;code&gt;mutate()&lt;/code&gt; adds a new variable called &lt;em&gt;selected_node&lt;/em&gt;, which tags those nodes with TRUE. The new variable and value is retained once the rest of the nodes are restored via the &lt;code&gt;unmorph()&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;To keep the change, the &lt;em&gt;shortest&lt;/em&gt; variable is updated with the changes made to both edges and nodes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest &amp;lt;- shortest %&amp;gt;%
  mutate(selected_node = TRUE) %&amp;gt;%
  activate(edges) %&amp;gt;%
  mutate(selected_edge = TRUE) %&amp;gt;%
  unmorph() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next step is to coerce each NA into a 1, and the shortest route into a 2. This will allow us to easily re-arrange the order that the edges are drawn in the plot, ensuring that the route will be drawn at the top.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest &amp;lt;- shortest %&amp;gt;%
  activate(nodes) %&amp;gt;%
  mutate(selected_node = ifelse(is.na(selected_node), 1, 2)) %&amp;gt;%
  activate(edges) %&amp;gt;%
  mutate(selected_edge = ifelse(is.na(selected_edge), 1, 2)) %&amp;gt;%
  arrange(selected_edge)

shortest&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tbl_graph: 59 nodes and 130 edges
## #
## # A directed simple graph with 1 component
## #
## # Edge Data: 130 x 4 (active)
##    from    to journey_time selected_edge
##   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;        &amp;lt;dbl&amp;gt;         &amp;lt;dbl&amp;gt;
## 1     1    39        186.              1
## 2     2    40         97.5             1
## 3     3    40        146.              1
## 4     4    39        225.              1
## 5     6    39        161.              1
## 6     7    39        358.              1
## # … with 124 more rows
## #
## # Node Data: 59 x 4
##   name               title              label                 selected_node
##   &amp;lt;chr&amp;gt;              &amp;lt;chr&amp;gt;              &amp;lt;chr&amp;gt;                         &amp;lt;dbl&amp;gt;
## 1 AIX EN PROVENCE T… Aix En Provence T… &amp;quot;Aix\nEn\nProvence\n…             1
## 2 ANGERS SAINT LAUD  Angers Saint Laud  &amp;quot;Angers\nSaint\nLaud&amp;quot;             1
## 3 ANGOULEME          Angouleme          Angouleme                         1
## # … with 56 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A simple way to plot the route is to use the &lt;em&gt;selected_&lt;/em&gt; variables to modify the &lt;code&gt;alpha&lt;/code&gt;. This will highlight the shortest path, without completely removing the other stations. This is a personal design choice, so experimenting with different ways of highlighting the results is always recommended.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest %&amp;gt;%
  ggraph(layout = &amp;quot;kk&amp;quot;) +
    geom_edge_diagonal(aes(alpha = selected_edge), color = &amp;quot;gray&amp;quot;) +
    geom_node_text(aes(label = label, color =name, alpha = selected_node ), size = 3) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2019-02-28-intro-to-graph-analysis_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;selected_&lt;/em&gt; fields can also be used in other &lt;code&gt;dplyr&lt;/code&gt; functions to analyze the results. For example, to know the aggregate information about the trip, &lt;em&gt;selected_edge&lt;/em&gt; is used to filter the edges, and then the totals can be calculated. There is no &lt;code&gt;summarise()&lt;/code&gt; function for graph tables; this make sense because the graph table would become a summarized table with such a function. Since the end result we seek is a total rather than another graph table, a simple &lt;code&gt;as_tibble()&lt;/code&gt; command will coerce the edges, which will then allows us to finish the calculation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest %&amp;gt;%
  activate(edges) %&amp;gt;%
  filter(selected_edge == 2) %&amp;gt;%
  as_tibble() %&amp;gt;%
  summarise(
    total_stops = n() - 1,
    total_time = round(sum(journey_time) / 60)
    )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 1 x 2
##   total_stops total_time
##         &amp;lt;dbl&amp;gt;      &amp;lt;dbl&amp;gt;
## 1           8         23&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;re-using-the-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Re-using the code&lt;/h2&gt;
&lt;p&gt;To compile most of the code in a single chunk, here is an example of how to re-run the shortest path for a different set of stations: the Laval and Montpellier stations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;from &amp;lt;- which(stations == &amp;quot;Montpellier&amp;quot;)
to &amp;lt;-  which(stations == &amp;quot;Laval&amp;quot;)

shortest &amp;lt;- graph_routes %&amp;gt;%
  morph(to_shortest_path, from, to, weights = journey_time) %&amp;gt;%
  mutate(selected_node = TRUE) %&amp;gt;%
  activate(edges) %&amp;gt;%
  mutate(selected_edge = TRUE) %&amp;gt;%
  unmorph() %&amp;gt;%
  activate(nodes) %&amp;gt;%
  mutate(selected_node = ifelse(is.na(selected_node), 1, 2)) %&amp;gt;%
  activate(edges) %&amp;gt;%
  mutate(selected_edge = ifelse(is.na(selected_edge), 1, 2)) %&amp;gt;%
  arrange(selected_edge)

shortest %&amp;gt;%
  ggraph(layout = &amp;quot;kk&amp;quot;) +
    geom_edge_diagonal(aes(alpha = selected_edge), color = &amp;quot;gray&amp;quot;) +
    geom_node_text(aes(label = label, color =name, alpha = selected_node ), size = 3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2019-02-28-intro-to-graph-analysis_files/figure-html/unnamed-chunk-17-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Additional, the same code can be recycled to obtain the trip summarized data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shortest %&amp;gt;%
  activate(edges) %&amp;gt;%
  filter(selected_edge == 2) %&amp;gt;%
  as_tibble() %&amp;gt;%
  summarise(
    total_stops = n() - 1,
    total_time = round(sum(journey_time) / 60)
    )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 1 x 2
##   total_stops total_time
##         &amp;lt;dbl&amp;gt;      &amp;lt;dbl&amp;gt;
## 1           3         10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;shiny-app&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shiny app&lt;/h2&gt;
&lt;p&gt;To see how to use this kind of analysis inside Shiny, please refer to &lt;a href=&#34;https://beta.rstudioconnect.com/content/4606/&#34;&gt;this application&lt;/a&gt;. It lets the user select two stations, and it returns the route, plus the summarized data. The source code is embedded in the app.&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2019/03/06/intro-to-graph-analysis/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>Database Queries With R</title>
      <link>https://rviews.rstudio.com/2017/10/18/database-queries-with-r/</link>
      <pubDate>Wed, 18 Oct 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/10/18/database-queries-with-r/</guid>
      <description>
        


&lt;p&gt;There are many ways to query data with R. This post shows you three of the most common ways:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Using &lt;code&gt;DBI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;dplyr&lt;/code&gt; syntax&lt;/li&gt;
&lt;li&gt;Using R Notebooks&lt;/li&gt;
&lt;/ol&gt;
&lt;div id=&#34;background&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;Several recent package improvements make it easier for you to use databases with R. The query examples below demonstrate some of the capabilities of these R packages.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rstats-db.github.io/DBI//index.html&#34;&gt;DBI&lt;/a&gt;. The &lt;code&gt;DBI&lt;/code&gt; specification has gone through many &lt;a href=&#34;https://www.r-consortium.org/blog/2017/05/15/improving-dbi-a-retrospect&#34;&gt;recent improvements&lt;/a&gt;. When working with databases, you should always use packages that are &lt;code&gt;DBI&lt;/code&gt;-compliant.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://dplyr.tidyverse.org/&#34;&gt;dplyr&lt;/a&gt; &amp;amp; &lt;a href=&#34;http://dbplyr.tidyverse.org/&#34;&gt;dbplyr&lt;/a&gt;. The &lt;code&gt;dplyr&lt;/code&gt; package now has a generalized SQL backend for talking to databases, and the new &lt;code&gt;dbplyr&lt;/code&gt; package translates R code into database-specific variants. As of this writing, SQL variants are supported for the following databases: Oracle, Microsoft SQL Server, PostgreSQL, Amazon Redshift, Apache Hive, and Apache Impala. More will follow over time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rstats-db/odbc&#34;&gt;odbc&lt;/a&gt;. The &lt;code&gt;odbc&lt;/code&gt; R package provides a standard way for you to connect to any database as long as you have an ODBC driver installed. The &lt;code&gt;odbc&lt;/code&gt; R package is &lt;code&gt;DBI&lt;/code&gt;-compliant, and is recommended for ODBC connections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RStudio also made recent improvements to its products so they work better with databases.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.rstudio.com/2017/10/09/rstudio-v1.1-released/&#34;&gt;RStudio IDE (v1.1)&lt;/a&gt;. With the latest version of the RStudio IDE, you can connect to, explore, and view data in a variety of databases. The IDE has a wizard for setting up new connections, and a tab for exploring established connections. These new features are extensible and will work with any R package that has a &lt;a href=&#34;https://rstudio.github.io/rstudio-extensions/connections-contract.html&#34;&gt;connections contract&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.rstudio.com/products/drivers/&#34;&gt;RStudio Professional Drivers&lt;/a&gt;. If you are using RStudio professional products, you can download RStudio Professional Drivers for no additional cost. The examples below use the Oracle ODBC driver. If you are using open-source tools, you can bring your own driver or use community packages – many open-source drivers and community packages exist for connecting to a variety of databases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using databases with R is a broad subject and there is more work to be done. An earlier blog post discussed &lt;a href=&#34;https://blog.rstudio.com/2017/06/27/dbplyr-1-1-0/&#34;&gt;our vision&lt;/a&gt;. Part of that vision was to create a website where you can find everything about databases and R in one place. To learn more, visit our site at &lt;a href=&#34;http://db.rstudio.com/best-practices/drivers&#34;&gt;db.rstudio.com&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-query-bank-data-in-an-oracle-database&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Example: Query bank data in an Oracle database&lt;/h3&gt;
&lt;p&gt;In this example, we will query bank data in an Oracle database. We connect to the database by using the &lt;code&gt;DBI&lt;/code&gt; and &lt;code&gt;odbc&lt;/code&gt; packages. This specific connection requires a database driver and a data source name (DSN) that have both been configured by the system administrator. Your connection might use another method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;library(DBI)
library(dplyr)
library(dbplyr)
library(odbc)
con &amp;lt;- dbConnect(odbc::odbc(), &amp;quot;Oracle DB&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;query-using-dbi&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;1. Query using &lt;code&gt;DBI&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;You can query your data with &lt;code&gt;DBI&lt;/code&gt; by using the &lt;code&gt;dbGetQuery()&lt;/code&gt; function. Simply paste your SQL code into the R function as a quoted string. This method is sometimes referred to as &lt;em&gt;pass through SQL code&lt;/em&gt;, and is probably the simplest way to query your data. Care should be used to escape your quotes as needed. For example, &lt;code&gt;&#39;yes&#39;&lt;/code&gt; is written as &lt;code&gt;\&#39;yes\&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dbGetQuery(con,&amp;#39;
  select &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;,
  sum(case when &amp;quot;term_deposit&amp;quot; = \&amp;#39;yes\&amp;#39; then 1.0 else 0.0 end) as subscribe,
  count(*) as total
  from &amp;quot;bank&amp;quot;
  group by &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;
&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;query-using-dplyr-syntax&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;2. Query using dplyr syntax&lt;/h3&gt;
&lt;p&gt;You can write your code in &lt;code&gt;dplyr&lt;/code&gt; syntax, and &lt;code&gt;dplyr&lt;/code&gt; will translate your code into SQL. There are several benefits to writing queries in &lt;code&gt;dplyr&lt;/code&gt; syntax: you can keep the same consistent language both for R objects and database tables, no knowledge of SQL or the specific SQL variant is required, and you can take advantage of the fact that &lt;code&gt;dplyr&lt;/code&gt; uses &lt;a href=&#34;http://dbplyr.tidyverse.org/articles/dbplyr.html&#34;&gt;lazy evaluation&lt;/a&gt;. &lt;code&gt;dplyr&lt;/code&gt; syntax is easy to read, but you can always inspect the SQL translation with the &lt;code&gt;show_query()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;q1 &amp;lt;- tbl(con, &amp;quot;bank&amp;quot;) %&amp;gt;%
  group_by(month_idx, year, month) %&amp;gt;%
  summarise(
    subscribe = sum(ifelse(term_deposit == &amp;quot;yes&amp;quot;, 1, 0)),
    total = n())
show_query(q1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;SQL&amp;gt;
SELECT &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;, SUM(CASE WHEN (&amp;quot;term_deposit&amp;quot; = &amp;#39;yes&amp;#39;) THEN (1.0) ELSE (0.0) END) AS &amp;quot;subscribe&amp;quot;, COUNT(*) AS &amp;quot;total&amp;quot;
FROM (&amp;quot;bank&amp;quot;) 
GROUP BY &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;query-using-an-r-notebooks&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;3. Query using an R Notebooks&lt;/h3&gt;
&lt;p&gt;Did you know that you can run SQL code in an &lt;a href=&#34;http://rmarkdown.rstudio.com/r_notebooks.html&#34;&gt;R Notebook&lt;/a&gt; code chunk? To use SQL, open an &lt;a href=&#34;http://rmarkdown.rstudio.com/r_notebooks.html&#34;&gt;R Notebook&lt;/a&gt; in the RStudio IDE under the &lt;strong&gt;File &amp;gt; New File&lt;/strong&gt; menu. Start a new code chunk with &lt;code&gt;{sql}&lt;/code&gt;, and specify your connection with the &lt;code&gt;connection=con&lt;/code&gt; code chunk option. If you want to send the query output to an R dataframe, use &lt;code&gt;output.var = &amp;quot;mydataframe&amp;quot;&lt;/code&gt; in the code chunk options. When you specify &lt;code&gt;output.var&lt;/code&gt;, you will be able to use the output in subsequent R code chunks. In this example, we use the output in &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```{sql, connection=con, output.var = &amp;quot;mydataframe&amp;quot;}
SELECT &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;, SUM(CASE WHEN (&amp;quot;term_deposit&amp;quot; = &amp;#39;yes&amp;#39;) THEN (1.0) ELSE (0.0) END) AS &amp;quot;subscribe&amp;quot;,
COUNT(*) AS &amp;quot;total&amp;quot;
FROM (&amp;quot;bank&amp;quot;) 
GROUP BY &amp;quot;month_idx&amp;quot;, &amp;quot;year&amp;quot;, &amp;quot;month&amp;quot;
```&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```{r}
library(ggplot2)
ggplot(mydataframe, aes(total, subscribe, color = year)) +
  geom_point() +
  xlab(&amp;quot;Total contacts&amp;quot;) +
  ylab(&amp;quot;Term Deposit Subscriptions&amp;quot;) +
  ggtitle(&amp;quot;Contact volume&amp;quot;)
```&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;/post/2017-10-18-database-queries-with-R/bankggplot.png&#34; /&gt;

&lt;/div&gt;
&lt;p&gt;The benefits to using SQL in a code chunk are that you can paste your SQL code without any modification. For example, you do not have to escape quotes. If you are using the proverbial &lt;em&gt;spaghetti code&lt;/em&gt; that is hundreds of lines long, then a SQL code chunk might be a good option. Another benefit is that the SQL code in a code chunk is highlighted, making it very easy to read. For more information on SQL engines, see this page on &lt;a href=&#34;http://rmarkdown.rstudio.com/authoring_knitr_engines.html&#34;&gt;knitr language engines&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;There is no single best way to query data with R. You have many methods to chose from, and each has its advantages. Here are some of the advantages using the methods described in this article.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;34%&#34; /&gt;
&lt;col width=&#34;65%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Advantages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;DBI::dbGetQuery&lt;/li&gt;
&lt;/ol&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;Fewer dependencies required&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;ol start=&#34;2&#34; style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;dplyr syntax&lt;/li&gt;
&lt;/ol&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;Use the same syntax for R and database objects&lt;/li&gt;
&lt;li&gt;No knowledge of SQL required&lt;/li&gt;
&lt;li&gt;Code is standard across SQL variants&lt;/li&gt;
&lt;li&gt;Lazy evaluation&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;ol start=&#34;3&#34; style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;R Notebook SQL engine&lt;/li&gt;
&lt;/ol&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;Copy and paste SQL – no formatting required&lt;/li&gt;
&lt;li&gt;SQL syntax is highlighted&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;You can download the R Notebook for these examples &lt;a href=&#34;http://rpubs.com/nwstephens/318586&#34;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/10/18/database-queries-with-r/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>Visualizations with R and Databases</title>
      <link>https://rviews.rstudio.com/2017/08/16/visualizations-with-r-and-databases/</link>
      <pubDate>Wed, 16 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/08/16/visualizations-with-r-and-databases/</guid>
      <description>
        


&lt;div id=&#34;the-challenge&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Challenge&lt;/h2&gt;
&lt;p&gt;Visualizations are one of R’s strengths. There are many functions and packages that create complex plots, often with one simple command. These plotting functions do two things: first, they take the raw data and run the calculations needed for a given visualization, and second, they draw the plot. If the source of the data resides within a database, the usual approach is to import all of the data and then create the plot. This is a problem, especially if the data is large.&lt;/p&gt;
&lt;p&gt;A strategy to address this problem is found in the new &lt;a href=&#34;http://db.rstudio.com/&#34;&gt;Database with RStudio&lt;/a&gt; website. The &lt;a href=&#34;http://db.rstudio.com/visualization/&#34;&gt;Creating Visualizations&lt;/a&gt; page outlines a solution that introduces the &lt;em&gt;“Transform in Database, plot in R”&lt;/em&gt; concept, and demonstrates its practical implementation. The article focused on knowledge sharing, rather than on providing a tool.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introducing-dbplot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introducing &lt;code&gt;dbplot&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The new &lt;code&gt;dbplot&lt;/code&gt; package is meant to collect multiple functions for in-database visualization code. It implements the principles laid out in the &lt;a href=&#34;http://db.rstudio.com/visualization/&#34;&gt;Creating Visualizations&lt;/a&gt; page, and it provides three types of functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Helper functions that return a &lt;code&gt;ggplot2&lt;/code&gt; visualization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Helper functions that return the results of the plot’s calculations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;db_bin()&lt;/code&gt; function introduced in the &lt;strong&gt;Creating Visualizations&lt;/strong&gt; page&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The package provides calculations or “base” &lt;code&gt;ggplot2&lt;/code&gt; visualizations for the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bar plot&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Line plot&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Histogram&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Raster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Install &lt;code&gt;dbplot&lt;/code&gt; from GitHub using the &lt;code&gt;devtools&lt;/code&gt; package&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;quot;edgararuiz/dbplot&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;This example will use a Microsoft SQL Server database connection to provide a quick glance of how the package works. For more examples, please visit the &lt;a href=&#34;https://github.com/edgararuiz/dbplot&#34;&gt;package’s GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;dbplot-functions&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;strong&gt;dbplot&lt;/strong&gt; functions&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;dbplot_histogram()&lt;/code&gt; function creates a 30-bin histogram by default. Because it uses &lt;code&gt;dplyr&lt;/code&gt; commands to perform the bin calculations, the function will work with any database that has &lt;code&gt;dplyr&lt;/code&gt; support, including &lt;code&gt;sparklyr&lt;/code&gt;. The only caveat is that the database must support basic functions like &lt;code&gt;max()&lt;/code&gt; and &lt;code&gt;min()&lt;/code&gt;, which some database types do not support.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dbplyr)

tbl(con, &amp;quot;airports&amp;quot;) %&amp;gt;% 
  dbplot_histogram(alt)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-08-14-database-visualize_files/figure-html/unnamed-chunk-3-1.png&#34;, width = 500, height = 400&gt;&lt;/p&gt;
&lt;p&gt;This example shows how the resulting plot object can be further refined after the &lt;code&gt;dbplot_histogram()&lt;/code&gt; function returns a plot:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl(con, &amp;quot;airports&amp;quot;) %&amp;gt;% 
  dbplot_histogram(alt, binwidth = 700) + 
  labs(title = &amp;quot;Airports Altitude&amp;quot;) +
  theme_minimal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-08-14-database-visualize_files/figure-html/unnamed-chunk-4-1.png&#34;, width = 500, height = 400&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;db_compute-functions&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;strong&gt;db_compute&lt;/strong&gt; functions&lt;/h3&gt;
&lt;p&gt;If more control over the plot is needed, then the &lt;code&gt;db_compute_bins()&lt;/code&gt; function returns a data frame with the lowest value of each bin and the record count per bin:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl(con, &amp;quot;airports&amp;quot;) %&amp;gt;% 
  db_compute_bins(alt)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;## # A tibble: 28 x 2
##       alt count
##     &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
##  1  -54.0   559
##  2  250.4   176
##  3  554.8   203
##  4  859.2   131
##  5 1163.6    82
##  6 1468.0    40
##  7 1772.4    20
##  8 2076.8    18
##  9 2381.2    16
## 10 2685.6    12
## # ... with 18 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The results of the compute command can then be piped into a plot:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tbl(con, &amp;quot;airports&amp;quot;) %&amp;gt;% 
  db_compute_bins(alt) %&amp;gt;%
  ggplot() +
  geom_col(aes(alt, count, fill = count))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-08-14-database-visualize_files/figure-html/unnamed-chunk-6-1.png&#34;, width = 500, height = 400&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;db_bin&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;strong&gt;db_bin()&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;dbplot&lt;/code&gt; package includes the &lt;code&gt;db_bin()&lt;/code&gt; function, first introduced in the &lt;strong&gt;Creating Visualizations&lt;/strong&gt; page. For more information, please read the &lt;a href=&#34;http://db.rstudio.com/visualization/#histogram&#34;&gt;Histogram&lt;/a&gt; section.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;db_bin(any_field)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;## (((max(any_field) - min(any_field))/(30)) * ifelse((as.integer(floor(((any_field) - 
##     min(any_field))/((max(any_field) - min(any_field))/(30))))) == 
##     (30), (as.integer(floor(((any_field) - min(any_field))/((max(any_field) - 
##     min(any_field))/(30))))) - 1, (as.integer(floor(((any_field) - 
##     min(any_field))/((max(any_field) - min(any_field))/(30))))))) + 
##     min(any_field)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;next-steps&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;More plots will be possible as &lt;code&gt;dplyr&lt;/code&gt;-to-SQL translations are fine-tuned and enhanced. The &lt;code&gt;dbplot&lt;/code&gt; package will be the place where new calculations and plots will be implemented.&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/08/16/visualizations-with-r-and-databases/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>What is the tidyverse?</title>
      <link>https://rviews.rstudio.com/2017/06/08/what-is-the-tidyverse/</link>
      <pubDate>Thu, 08 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/06/08/what-is-the-tidyverse/</guid>
      <description>
        
&lt;!-- BLOGDOWN-HEAD --&gt;
&lt;!-- /BLOGDOWN-HEAD --&gt;

&lt;!-- BLOGDOWN-BODY-BEFORE --&gt;
&lt;!-- /BLOGDOWN-BODY-BEFORE --&gt;
&lt;p&gt;Last week, I had the opportunity to talk to a group of Master’s level &lt;a href=&#34;http://www.csueastbay.edu/about/institutional-effectiveness/educ-effectiveness/program-portfolios/cos/msstat/&#34;&gt;Statistics&lt;/a&gt; and &lt;a href=&#34;http://catalog.csueastbay.edu/preview_program.php?catoid=4&amp;amp;poid=1590&#34;&gt;Business Analytics&lt;/a&gt; students at Cal State East Bay about R and Data Science. Many in my audience were adult students coming back to school with job experience writing code in Java, Python and SAS. It was a pretty sophisticated crowd, but not surprisingly, their R skills were stitched together in a way that left some big gaps. Many for example, didn’t fully understand the importance of CRAN Task Views as curated source for the best packages to support their work in machine learning, time series and the other areas of Statistics they were studying. So, it made sense that even though &lt;code&gt;ggplot2&lt;/code&gt; and &lt;code&gt;dplyr&lt;/code&gt; were mentioned in some of the student’s questions, a faculty member present asked: “What is the tidyverse?” in an attempt to cover an area that he knew was one of those gaps.&lt;/p&gt;
&lt;p&gt;There is an incredible amount of good material available online about the tidyverse, and I will point to some of that below. But here, I’ll elaborate on the answer I gave during the Q&amp;amp;A.&lt;/p&gt;
&lt;div id=&#34;the-basics&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Basics&lt;/h2&gt;
&lt;p&gt;The tidyverse is a coherent system of packages for data manipulation, exploration and visualization that share a common design philosophy. These were mostly developed by Hadley Wickham himself, but they are now being expanded by several contributors. Tidyverse packages are intended to make statisticians and data scientists more productive by guiding them through workflows that facilitate communication, and result in reproducible work products. Fundamentally, the tidyverse is about the connections between the tools that make the workflow possible.&lt;/p&gt;
&lt;p&gt;It is also the case that the tidyverse is work in progress. You can find the current state of development at &lt;a href=&#34;http://tidyverse.org/&#34;&gt;tidyverse.org&lt;/a&gt;. Clicking on the icon for each package on this website will bring you to detailed documentation for each package. The following figure illustrates a canonical data science workflow, and shows how the individual packages fit in.&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;/post/2017-06-09-What-is-the-tidyverse_files/tidyverse1.png&#34; /&gt;

&lt;/div&gt;
&lt;p&gt;If you have some experience with R, you ought to be able to jump right into the online documentation and find your way around. If you are new to R, and maybe new to data science as well, you can’t do any better than work through the book &lt;a href=&#34;http://r4ds.had.co.nz/&#34;&gt;R for Data Science&lt;/a&gt; by Hadley Wickham and Garrett Grolemund.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;advantages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Advantages&lt;/h2&gt;
&lt;p&gt;The advantages of the tidyverse include consistent functions, workflow coverage, a path to data science education, a parsimonious approach to the development of data science tools, and the possibility of greater productivity.&lt;/p&gt;
&lt;div id=&#34;consistency&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Consistency&lt;/h3&gt;
&lt;p&gt;The tidyverse aspires to consistency on multiple levels. Examples of “micro”-level consistency include the convention of having variable names glide along in &lt;code&gt;snake_case&lt;/code&gt;, and the signatures of tidyverse functions follow a regular pattern. (The first formal argument is always a data frame that provides the function’s input.) Higher-level consistency includes the idea of tidy data - a data frame where each row is an observation and each column contains the value of a single variable - and the way in which the pipe operator, &lt;code&gt;%&amp;gt;%&lt;/code&gt;, channels the flow of tidy operations. Under the covers, there are even more levels of structure that aid the pursuit of consistency, including uniform standards for package organization, testing procedures, coding style, etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;coverage&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Coverage&lt;/h3&gt;
&lt;p&gt;The workflow shown above, with tidyverse packages associated with the various steps, or more usually rendered with the following iconic tidyverse diagram, preceded and motivated the development of the tidyverse.&lt;/p&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;/post/2017-06-09-What-is-the-tidyverse_files/tidyverse2.png&#34; /&gt;

&lt;/div&gt;
&lt;p&gt;It is an abstraction of the canonical data analysis workflow that has always guided statisticians, but now informs data science as a map to organize, streamline, automate and optimize the various processes involved. The fact that tidyverse packages are associate with all of the processes indicates that it comprises enough fundamental building blocks to support the entire end-to-end workflow for a variety of data sources and analysis goals. Moreover, the relatively recent addition of the &lt;code&gt;purrr&lt;/code&gt; package extends the reach of the tidyverse to support the creation of new data science tools.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;critical-mass&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Critical Mass&lt;/h3&gt;
&lt;p&gt;A great strength of the R language is that with over ten thousand user contributed packages on CRAN alone, it has a lot to offer. This kind of organic growth makes it inevitable that packages will offer overlapping features. Users have to make decisions about which package, or suite of packages, they will make the effort to learn. For many users, the decision hinges on whether a collection of packages visibly supports important work. Does it have a large community of users and is it backed by committed developers and maintainers? All of the signals indicate that (at least, among R-using data scientists) the tidyverse has reached critical mass. For example, the tidyverse package has been downloaded 50,000 times in the last month. Moreover, it appears that tidyverse principles are propagating into other application areas. The &lt;a href=&#34;http://www.business-science.io/code-tools/2017/01/01/tidyquant-introduction.html&#34;&gt;tidyquant package&lt;/a&gt;, for example, is a serious attempt to bring tidy principles to Finance.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;education&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Education&lt;/h3&gt;
&lt;p&gt;A typical R user gets involved with R in the first place through a desire to compute in some quantitative field. The path to R competency frequently begins with mastering a small number of relevant functions. Statisticians, for example, may learn to read in data from a &lt;code&gt;.csv&lt;/code&gt; file and build a linear regression model with &lt;code&gt;lm()&lt;/code&gt;. Financial analysts may be introduced to R through a package like &lt;code&gt;quantmod&lt;/code&gt;, which enables a new user to do quite a bit of real work. The tidyverse provides the path of least resistance, or “pit of success”, for data scientists interested in R. For example, the small number of compatible building blocks provided by dplyr enable even a relatively inexperienced user to tidy up a messy data set quickly and easily.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;parsimony&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Parsimony&lt;/h3&gt;
&lt;p&gt;The packages and functions of the tidyverse are the result of trial-and-error experimentation carried out over several years, to find a minimum set of functions that are sufficient to enable the canonical data science workflow. Those of you who have been following Hadley’s work will remember &lt;code&gt;cast()&lt;/code&gt; and &lt;code&gt;melt()&lt;/code&gt; from the &lt;code&gt;reshape&lt;/code&gt; and &lt;code&gt;reshape2&lt;/code&gt; packages, and &lt;code&gt;ddply()&lt;/code&gt; from the &lt;code&gt;plyr&lt;/code&gt; package, which were early attempts to find a vocabulary for wrangling data frames. After several attempts to identify and construct the most advantages set of primitive building blocks, the tidyverse has matured into its present form.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;productivity&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Productivity&lt;/h3&gt;
&lt;p&gt;Hadley has always been clear that a major goal for the tidyverse - and indeed much of his work over the years - has been to help anyone who needs to analyze data work productively, and he is fond of quoting &lt;a href=&#34;https://en.wikipedia.org/wiki/Hal_Abelson&#34;&gt;Hal Abelson&lt;/a&gt;: “Programs must be written for people to read and only incidentally for machines to execute”. My take is that a major reason for the popularity of tidyverse packages is that they help people achieve and maintain &lt;a href=&#34;https://en.wikipedia.org/wiki/Flow_(psychology)&#34;&gt;flow&lt;/a&gt; in their daily data analysis work.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;some-limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Some Limitations&lt;/h2&gt;
&lt;p&gt;The tidyverse, of course, is not without limitations. Some of these are due to factors that are beyond the designer’s control, and others may be by design. Limitations of the first kind may arise from a lack of agreement as to whether some data can be, or should be, forced into a “rectangular” data structure. For example, although there are scientists and data scientists working in genomics that are fans of &lt;code&gt;dplyr&lt;/code&gt; and &lt;code&gt;ggplot2&lt;/code&gt;, much of the work done in the &lt;a href=&#34;https://www.bioconductor.org/&#34;&gt;Bioconductor Project&lt;/a&gt; remains outside of the tidyverse workflow.&lt;/p&gt;
&lt;p&gt;The need for the close coordination of tidyverse packages produces some limitations of the second sort. There are many high-quality R packages that are of great use to data scientists, but based on design goals that differ from those of the tidyverse. There will always be more than the tidyverse.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-bigger-picture&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A Bigger Picture&lt;/h2&gt;
&lt;p&gt;A powerful, but perhaps under-appreciated, capability of the R language is its ability to support the design and programming of Domain Specific Languages. Joe Cheng highlighted this feature in an &lt;a href=&#34;https://rviews.rstudio.com/2017/01/04/interview-with-joe-cheng/&#34;&gt;interview&lt;/a&gt; he gave to R Views last year. He described R as being “shockingly close to LISP”, of which Joe says: “it’s almost like you change the language itself to be a DSL for whatever problem you’re trying to solve … the elegant, terse syntax of dplyr and the pipe operator are possible because of how malleable a language R is, and how great it is for writing DSLs in it.”&lt;/p&gt;
&lt;p&gt;So, from a wider perspective, the tidyverse can be seen as sub-dialect of the R language that is evolving to express ideas and tasks inherent in Data Science workflows and software development. This dialect may not be for everyone, but it does seem to be helping many R fluent data scientists frame their conversations.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;some-resources&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Some Resources&lt;/h2&gt;
&lt;p&gt;The following are some resources that you may find helpful in learning and mastering the tidyverse.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href=&#34;https://www.rstudio.com/resources/videos/data-science-in-the-tidyverse/&#34;&gt;video&lt;/a&gt; of Hadley Wickham’s Keynote address at rstudio::conf 2017&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/rstudio/rstudio-conf/blob/master/2017/The_Tidyverse-Hadley_Wickham/tidyverse.pdf&#34;&gt;slides&lt;/a&gt; corresponding to the above video&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://r4ds.had.co.nz/&#34;&gt;R for Data Science&lt;/a&gt; by Hadley Wickham and Garrett Grolemund&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://tidytextmining.com/&#34;&gt;Text Mining with R&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://www.storybench.org/getting-started-with-tidyverse-in-r/&#34;&gt;Getting Started with the Tidyverse in R&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/06/08/what-is-the-tidyverse/&#39;;&lt;/script&gt;
      </description>
    </item>
    
    <item>
      <title>Databases using R</title>
      <link>https://rviews.rstudio.com/2017/05/17/databases-using-r/</link>
      <pubDate>Wed, 17 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://rviews.rstudio.com/2017/05/17/databases-using-r/</guid>
      <description>
        


&lt;div id=&#34;current-state&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Current State&lt;/h1&gt;
&lt;p&gt;Using databases is unavoidable for those who analyze data as part of their jobs. As R developers, our first instinct may be to approach databases the same way we do regular files. We may attempt to read the data either all at once or as few times as possible. The aim is to reduce the number of times we go back to the data ‘well’, so our queries extract as much data as possible. After that, we spend cycles analyzing the data in memory. Here is what this model looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-05-11-databases-using-r_files/today.png&#34;  height=&#34;400&#34; width=&#34;400&#34;&gt;&lt;/p&gt;
&lt;p&gt;Because the volume of data is significant with this approach, we usually attempt to come up with strategies to minimize the resources and time it takes to analyze the data. We may try to retrieve all rows of a few columns, or a few rows of several of columns. Another tactic is to save the query results into individual files for later analysis.&lt;/p&gt;
&lt;p&gt;An improvement to the current approach would be to use the database’s SQL Engine to perform as much of the data exploration as possible. An enterprise-grade SQL server will have more power, and will be better tuned, to execute transformations of large amounts of data. Our goal would then be to bring into R a more targeted data set that will be used for visualization and modeling.&lt;/p&gt;
&lt;p&gt;This improvement comes at a cost: we will need to know how to write SQL queries, and will have to switch between both languages. We may also end up using an external querying tool that is able to provide a list of tables and inline SQL code helpers. Of course, this involves switching between tools. On a personal note, I used to switch from R to Microsoft SQL Management Studio. After I that, I would bring the finalized query back into my code in R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-better-way&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A better way&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-05-11-databases-using-r_files/better.png&#34;  height=&#34;400&#34; width=&#34;400&#34;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;dplyr&lt;/code&gt; package simplifies data transformation. It provides a consistent set of functions, called verbs, that can be used in succession and interchangeably to gain understanding of the data iteratively. The first time I re-wrote R code using &lt;code&gt;dplyr&lt;/code&gt;, the new script was at least half as long and much easier to understand.&lt;/p&gt;
&lt;p&gt;Another nice thing about &lt;code&gt;dplyr&lt;/code&gt; is that it can interact with databases directly. It accomplishes this by translating the &lt;code&gt;dplyr&lt;/code&gt; verbs into SQL queries. This incredibly convenient feature allows us to ‘speak’ directly with the database from R, thus resolving the issues brought up in the previous section:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run data exploration over all of the data&lt;/strong&gt; - Instead of coming up with a plan to decide what data to import, we can focus on analyzing the data inside the database, which in turn should yield faster insights.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the SQL Engine to run the data transformations&lt;/strong&gt; - We are, in effect, pushing the computation to the database because &lt;code&gt;dplyr&lt;/code&gt; is sending SQL queries to the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collect a targeted dataset&lt;/strong&gt; - After become familiar with the data and choosing the data points that will either be shared or modeled, a final query can then be used to bring back only that data into memory in R.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;All your code is in R!&lt;/strong&gt; - Because we are using &lt;code&gt;dplyr&lt;/code&gt; to communicate with the database, there is no need to change language, or tools, to perform the data exploration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example&lt;/h1&gt;
&lt;p&gt;There are three things that we will need to get started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A database we can access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A database driver installed in either our workstation or RStudio Server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All of the required packages installed in R&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this section, we will demonstrate how to access a Microsoft SQL Server database from a workstation that is running on Microsoft Windows.&lt;/p&gt;
&lt;div id=&#34;database-driver&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Database Driver&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;database driver&lt;/strong&gt; is a program that allows the workstation and the database to communicate. In Microsoft Windows, the drivers that connect to MS SQL databases are installed by default. We need the &lt;strong&gt;name&lt;/strong&gt; of the driver that will be used inside our code in R. The easiest way to do this is to open the ODBC Data Source Administrator. To find it in your, system please refer to this article: &lt;a href=&#34;https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/check-the-odbc-sql-server-driver-version-windows&#34;&gt;Check the ODBC SQL Server Driver Version (Windows)&lt;/a&gt; . Once the administrator program is open, click on the &lt;strong&gt;Drivers&lt;/strong&gt; tab. In my laptop, these are the drivers available. I will use &lt;strong&gt;SQL Server&lt;/strong&gt; for the Driver argument in my connection in R.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/post/2017-05-11-databases-using-r_files/odbc.png&#34;  height=&#34;400&#34; width=&#34;400&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;r-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;R packages&lt;/h2&gt;
&lt;p&gt;Besides &lt;code&gt;dplyr&lt;/code&gt;, the following packages are required:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;odbc&lt;/code&gt; - This is the interface between the database driver and R&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DBI&lt;/code&gt; - Standardizes the functions related to database operations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dbplyr&lt;/code&gt; - Enables &lt;code&gt;dplyr&lt;/code&gt; to interact with databases. It also contains the vendor-specific SQL translations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The database accessibility feature is still being developed, so we will use the development versions of &lt;code&gt;dbplyr&lt;/code&gt; and &lt;code&gt;dplyr&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;devtools::install_github(&amp;quot;tidyverse/dplyr&amp;quot;)
devtools::install_github(&amp;quot;tidyverse/dbplyr&amp;quot;)
devtools::install_github(&amp;quot;rstats-db/odbc&amp;quot;)
install.packages(&amp;quot;DBI&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;connect-to-the-database&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Connect to the database&lt;/h2&gt;
&lt;p&gt;We will use the &lt;code&gt;dbConnect()&lt;/code&gt; function from the &lt;code&gt;DBI&lt;/code&gt; package to connect to the database. The value for the &lt;code&gt;Driver&lt;/code&gt; argument is the name we determined in the &lt;em&gt;Database Driver&lt;/em&gt; section above.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;library(DBI)

con &amp;lt;- dbConnect(odbc::odbc(),
                   Driver    = &amp;quot;SQL Server&amp;quot;, 
                   Server    = &amp;quot;localhost&amp;quot;,
                   Database  = &amp;quot;airontime&amp;quot;,
                   UID       = [My User ID],
                   PWD       = [My Password],
                   Port      = 1433)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A very useful function in &lt;code&gt;DBI&lt;/code&gt; is &lt;code&gt;dbListTables()&lt;/code&gt;, which retrieves the names of available tables.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dbListTables(con)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;[1] &amp;quot;airlines&amp;quot; &amp;quot;airport&amp;quot;  &amp;quot;airports&amp;quot; &amp;quot;faithful&amp;quot; &amp;quot;flights&amp;quot;  &amp;quot;iris&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Another useful function is the &lt;code&gt;dbListFields&lt;/code&gt;, which returns a vector with all of the column names in a table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dbListFields(con, &amp;quot;flights&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;[1] &amp;quot;year&amp;quot;           &amp;quot;month&amp;quot;          &amp;quot;day&amp;quot;            &amp;quot;dep_time&amp;quot;       &amp;quot;sched_dep_time&amp;quot;  [6] &amp;quot;dep_delay&amp;quot;      &amp;quot;arr_time&amp;quot;       &amp;quot;sched_arr_time&amp;quot; &amp;quot;arr_delay&amp;quot;      &amp;quot;carrier&amp;quot;        [11] &amp;quot;flight&amp;quot;         &amp;quot;tailnum&amp;quot;        &amp;quot;origin&amp;quot;         &amp;quot;dest&amp;quot;           &amp;quot;air_time&amp;quot;       [16] &amp;quot;distance&amp;quot;       &amp;quot;hour&amp;quot;           &amp;quot;minute&amp;quot;         &amp;quot;time_hour&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;interacting-with-the-data-using-dplyr&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interacting with the data using dplyr&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;dplyr&lt;/code&gt;, we can easily preview a database. The &lt;code&gt;tbl()&lt;/code&gt; command creates a reference to the table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;library(dplyr)
tbl(con, &amp;quot;flights&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Source:     table&amp;lt;flights&amp;gt; [?? x 19]
Database:   Microsoft SQL Server 12.00.4422[username@localhost/airontime]

    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin  dest
   &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;    &amp;lt;int&amp;gt;          &amp;lt;int&amp;gt;     &amp;lt;dbl&amp;gt;    &amp;lt;int&amp;gt;          &amp;lt;int&amp;gt;     &amp;lt;dbl&amp;gt;   &amp;lt;chr&amp;gt;  &amp;lt;int&amp;gt;   &amp;lt;chr&amp;gt;  &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;
1   2013     1     1      517            515         2      830            819        11      UA   1545  N14228    EWR   IAH
2   2013     1     1      533            529         4      850            830        20      UA   1714  N24211    LGA   IAH
3   2013     1     1      542            540         2      923            850        33      AA   1141  N619AA    JFK   MIA
4   2013     1     1      544            545        -1     1004           1022       -18      B6    725  N804JB    JFK   BQN
5   2013     1     1      554            600        -6      812            837       -25      DL    461  N668DN    LGA   ATL
6   2013     1     1      554            558        -4      740            728        12      UA   1696  N39463    EWR   ORD
7   2013     1     1      555            600        -5      913            854        19      B6    507  N516JB    EWR   FLL
8   2013     1     1      557            600        -3      709            723       -14      EV   5708  N829AS    LGA   IAD
9   2013     1     1      557            600        -3      838            846        -8      B6     79  N593JB    JFK   MCO
10  2013     1     1      558            600        -2      753            745         8      AA    301  N3ALAA    LGA   ORD
# ... with more rows, and 5 more variables: air_time &amp;lt;dbl&amp;gt;, distance &amp;lt;dbl&amp;gt;, hour &amp;lt;dbl&amp;gt;, minute &amp;lt;dbl&amp;gt;, time_hour &amp;lt;dttm&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt; The &lt;code&gt;tally()&lt;/code&gt; verb in &lt;code&gt;dplyr&lt;/code&gt; returns the row count.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tally(tbl(con, &amp;quot;flights&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/br&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Source:     lazy query [?? x 1]
Database:   Microsoft SQL Server 12.00.4422[username@localhost/airontime]

       n
   &amp;lt;int&amp;gt;
1 336776&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt; When used against a database, the previous function is converted to a SQL query that works with MS SQL Server. The &lt;code&gt;show_query()&lt;/code&gt; function displays the translation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;show_query(tally(tbl(con, &amp;quot;flights&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;SQL&amp;gt; SELECT COUNT(*) AS &amp;quot;n&amp;quot; FROM &amp;quot;flights&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bringing-it-all-together&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bringing it all together&lt;/h2&gt;
&lt;p&gt;The last code sample shows how easy it is to find out what the top airlines are by number of flights. Additionally, we wish to see the names of the airlines and not their codes. The steps taken are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start with the &lt;code&gt;flights&lt;/code&gt; table and join it to the &lt;code&gt;carrier&lt;/code&gt; table to obtain the airline name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Group the data by the airline &lt;code&gt;name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tally the total rows by airline &lt;code&gt;name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Order the data by the resulting tallies in a descending order&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these steps are translated into a SQL statement and processed inside the database. We do not need to import the tables into R memory at any time, we just use &lt;code&gt;dplyr&lt;/code&gt; to get the results quickly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tbl(con, &amp;quot;flights&amp;quot;) %&amp;gt;%
  left_join(tbl(con, &amp;quot;airlines&amp;quot;), by = &amp;quot;carrier&amp;quot;) %&amp;gt;%
  group_by(name) %&amp;gt;%
  tally %&amp;gt;%
  arrange(desc(n))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Source:     lazy query [?? x 2]
Database:   Microsoft SQL Server 12.00.4422[username@localhost/airontime]
Ordered by: desc(n)

# S3: tbl_dbi
                       name     n
                      &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
 1    United Air Lines Inc. 58665
 2          JetBlue Airways 54635
 3 ExpressJet Airlines Inc. 54173
 4     Delta Air Lines Inc. 48110
 5   American Airlines Inc. 32729
 6                Envoy Air 26397
 7          US Airways Inc. 20536
 8        Endeavor Air Inc. 18460
 9   Southwest Airlines Co. 12275
10           Virgin America  5162
# ... with more rows&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;additional-resources&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Additional Resources&lt;/h1&gt;
&lt;p&gt;Here are links that will provide a deeper look into their respective subjects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://dplyr.tidyverse.org/&#34;&gt;dplyr’s Official Site&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/DBI/vignettes/DBI-1.html&#34;&gt;Vignette of the DBI package&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://r4ds.had.co.nz/&#34;&gt;R for Data Science&lt;/a&gt; - An online book that covers how to use &lt;code&gt;dplyr&lt;/code&gt; and other like packages that together are called the &lt;code&gt;tidyverse&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;When we have only one method available to us, it is sometimes hard to see its inherent flaws. The method does what we need, so we do our best to overcome its shortfalls.&lt;/p&gt;
&lt;p&gt;Our hope is that highlighting the issues related to importing large amounts of data into R, and the advantages of using &lt;code&gt;dplyr&lt;/code&gt; to interact with databases, will be the encouragement needed to learn more about &lt;code&gt;dplyr&lt;/code&gt; and to give it a try.&lt;/p&gt;
&lt;p&gt;We plan to continue writing about the subject of databases using R in future posts. We will cover different aspects and techniques to get the most out of working with these two great technologies.&lt;/p&gt;
&lt;/div&gt;

        &lt;script&gt;window.location.href=&#39;https://rviews.rstudio.com/2017/05/17/databases-using-r/&#39;;&lt;/script&gt;
      </description>
    </item>
    
  </channel>
</rss>
