<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/data-wrangling-within-the-tidyverse-the-design-philosophy-behind-the-sjmisc-package-rstats/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://strengejacke.wordpress.com/2017/02/08/data-wrangling-within-the-tidyverse-the-design-philosophy-behind-the-sjmisc-package-rstats/"> R – Strenge Jacke!</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I’m pleased to announce <a target="_blank" rel="nofollow" href="https://cran.r-project.org/package=sjmisc">sjmisc 2.3.0</a>, which was just updated on CRAN. The update might break existing code – however, functions were largely revised to work seamlessly within the <a target="_blank" rel="nofollow" href="http://tidyverse.org/">tidyverse</a>. In the long run, consistent design makes working with <strong>sjmisc</strong> more intuitive.</p>
<p>Basically, <strong>sjmisc</strong> covers two domains of functionality:</p>
<ul>
<li>Reading and writing data between R and other statistical software packages like SPSS, SAS or Stata and working with labelled data; this includes easy ways to get and set label attributes, to convert labelled vectors into factors (and vice versa), or to deal with multiple declared missing values etc.</li>
<li>Data transformation tasks like recoding, dichotomizing or grouping variables, setting and replacing missing values. The data transformation functions also support labelled data.</li>
</ul>
<p>This posting briefly describes some of the changes to the function design that do data transformation tasks. </p>
<h2>The design of data transformation functions</h2>
<p>The design of data transformation functions in this package follows, where appropriate, the <em>tidyverse-approach</em>, with the first argument of a function always being the data (either a data frame or vector), followed by variable names that should be processed by the function. If no variables are specified as argument, the function applies to the complete data that was indicated as first function argument.</p>
<h3>The data-argument</h3>
<p>A slight difference to dplyr-functions like <code>select()</code> or <code>filter()</code> is that the data-argument (the first argument of each function) may either be a data frame <em>or</em> a vector. The returned object for each function equals the type of the data-argument:</p>
<ul>
<li>If the data-argument is a vector, the function returns a vector.</li>
<li>If the data-argument is a data frame, the function returns a data frame.</li>
</ul>
<pre>library(sjmisc)
data(efc)

# returns a vector
x &lt;- rec(efc$e42dep, recodes = &quot;1,2=1; 3,4=2&quot;)
str(x)
#>  atomic [1:908] 2 2 2 2 2 2 2 2 2 2 ...
#>  - attr(*, &quot;label&quot;)= chr &quot;elder's dependency&quot;

# returns a data frame (a tibble, to be exactly)
rec(efc, e42dep, recodes = &quot;1,2=1; 3,4=2&quot;)

#> # A tibble: 908 × 1
#>    e42dep_r
#>       &lt;dbl>
#> 1         2
#> 2         2
#> 3         2
#> 4         2
#> 5         2
#> 6         2
#> 7         2
#> 8         2
#> 9         2
#> 10        2
#> # ... with 898 more rows</pre>
<p>This design-choice is mainly due to compatibility- and convenience-reasons. It does not affect the usual “tidyverse-workflow” or when using pipe-chains.</p>
<h3>The …-ellipses-argument</h3>
<p>The selection of variables specified in the <code>...</code>-ellipses-argument is powered by dplyr’s <code>select()</code>. This means, you can use existing functions like <code>:</code> to select a range of variables, or also use dplyr’s <em>select_helpers</em>, like <code>contains()</code> or <code>one_of()</code>. However, select_helpers must begin with a <code>~</code>-sign.</p>
<pre># select all variables with &quot;cop&quot; in their names, and also
# the range from c161sex to c175empl
rec(efc, ~contains(&quot;cop&quot;), c161sex:c175empl, recodes = &quot;0,1=0; else=1&quot;)

#> # A tibble: 908 × 12
#>    c161sex_r c172code_r c175empl_r c82cop1_r c83cop2_r c84cop3_r c85cop4_r
#>        &lt;dbl>      &lt;dbl>      &lt;dbl>     &lt;dbl>     &lt;dbl>     &lt;dbl>     &lt;dbl>
#> 1          1          1          0         1         1         1         1
#> 2          1          1          0         1         1         1         1
#> 3          0          0          0         1         1         0         1
#> 4          0          1          0         1         0         1         0
#> 5          1          1          0         1         1         0         1
#> 6          0          1          0         1         1         1         1
#> 7          1          1          0         1         1         1         0
#> 8          1          1          0         1         1         1         0
#> 9          1         NA          0         1         1         1         1
#> 10         1          1          0         1         1         0         1
#> # ... with 898 more rows, and 5 more variables: c86cop5_r &lt;dbl>,
#> #   c87cop6_r &lt;dbl>, c88cop7_r &lt;dbl>, c89cop8_r &lt;dbl>, c90cop9_r &lt;dbl>

# center all variables with &quot;age&quot; in name, variable c12hour
# and all variables from column 19 to 21
center(efc, c12hour, ~contains(&quot;age&quot;), 19:21)

#> # A tibble: 908 × 6
#>     c12hour_c barthtot_c  neg_c_7_c pos_v_4_c    e17age_c  c160age_c
#>         &lt;dbl>      &lt;dbl>      &lt;dbl>     &lt;dbl>       &lt;dbl>      &lt;dbl>
#> 1  -26.399113  10.453001  0.1502242 -0.476731   3.8787879  2.5371809
#> 2  105.600887  10.453001  8.1502242 -1.476731   8.8787879  0.5371809
#> 3   27.600887 -29.546999 -0.8497758  0.523269   2.8787879 26.5371809
#> 4  125.600887 -64.546999 -1.8497758  2.523269 -12.1212121 15.5371809
#> 5  125.600887 -39.546999  0.1502242  2.523269   4.8787879 -6.4628191
#> 6  -26.399113  -4.546999  7.1502242 -3.476731   5.8787879  2.5371809
#> 7  118.600887 -59.546999  3.1502242  0.523269  -5.1212121  7.5371809
#> 8   67.600887 -29.546999 -0.8497758  1.523269   7.8787879 13.5371809
#> 9  -14.399113 -49.546999  3.1502242  0.523269  -0.1212121  5.5371809
#> 10  -2.399113 -64.546999 -1.8497758  0.523269   3.8787879 -4.4628191
#> # ... with 898 more rows</pre>
<h2>The function-types</h2>
<p>There are two types of function designs:</p>
<h3>coercing/converting functions</h3>
<p>Functions like <code>to_factor()</code> or <code>add_labels()</code>, which convert variables into other types or add additional information like variable or value labels as attribute, typically <em>return the complete data frame</em> that was given as first argument. The variables specified in the <code>...</code>-ellipses argument are converted, all other variables remain unchanged.</p>
<pre>to_factor(efc, e42dep, e16sex)
#> # A tibble: 908 × 26
#>    c12hour e15relat e16sex e17age e42dep c82cop1 c83cop2 c84cop3 c85cop4
#>      &lt;dbl>    &lt;dbl> &lt;fctr>  &lt;dbl> &lt;fctr>   &lt;dbl>   &lt;dbl>   &lt;dbl>   &lt;dbl>
#> 1       16        2      2     83      3       3       2       2       2
#> 2      148        2      2     88      3       3       3       3       3
#> 3       70        1      2     82      3       2       2       1       4
#> 4      168        1      2     67      4       4       1       3       1
#> 5      168        2      2     84      4       3       2       1       2
#> 6       16        2      2     85      4       2       2       3       3
#> 7      161        1      1     74      4       4       2       4       1
#> 8      110        4      2     87      4       3       2       2       1
#> 9       28        2      2     79      4       3       2       3       2
#> 10      40        2      2     83      4       3       2       1       2
#> # ... with 898 more rows, and 17 more variables: c86cop5 &lt;dbl>,
#> #   c87cop6 &lt;dbl>, c88cop7 &lt;dbl>, c89cop8 &lt;dbl>, c90cop9 &lt;dbl>,
#> #   c160age &lt;dbl>, c161sex &lt;dbl>, c172code &lt;dbl>, c175empl &lt;dbl>,
#> #   barthtot &lt;dbl>, neg_c_7 &lt;dbl>, pos_v_4 &lt;dbl>, quol_5 &lt;dbl>,
#> #   resttotn &lt;dbl>, tot_sc_e &lt;dbl>, n4pstu &lt;dbl>, nur_pst &lt;dbl></pre>
<h3>transformation/recoding functions</h3>
<p>Functions like <code>rec()</code> or <code>dicho()</code>, which transform or recode variables, typically <em>do not</em> return the complete data frame that was given as first argument, but only the transformed and recoded variables specified in the <code>...</code>-ellipses argument. The reason for this is to preserve the original variable and not overwriting it with completeley new values.</p>
<pre>rec(efc, c82cop1, c83cop2, recodes = &quot;1,2=0; 3:4=2&quot;)
#> # A tibble: 908 × 2
#>    c82cop1_r c83cop2_r
#>        &lt;dbl>     &lt;dbl>
#> 1          2         0
#> 2          2         2
#> 3          0         0
#> 4          2         0
#> 5          2         0
#> 6          0         0
#> 7          2         0
#> 8          2         0
#> 9          2         0
#> 10         2         0
#> # ... with 898 more rows</pre>
<p>These variables usually get a suffix, so you can bind these variables as new columns to a data frame, for instance with <code>add_columns()</code>. <code>add_columns()</code> is useful if you want to bind/add columns within a pipe-chain <em>to the end</em> of a data frame.</p>
<pre>efc %>% 
  rec(c82cop1, c83cop2, recodes = &quot;1,2=0; 3:4=2&quot;) %>% 
  add_columns(efc)
#> # A tibble: 908 × 28
#>    c12hour e15relat e16sex e17age e42dep c82cop1 c83cop2 c84cop3 c85cop4
#>      &lt;dbl>    &lt;dbl>  &lt;dbl>  &lt;dbl>  &lt;dbl>   &lt;dbl>   &lt;dbl>   &lt;dbl>   &lt;dbl>
#> 1       16        2      2     83      3       3       2       2       2
#> 2      148        2      2     88      3       3       3       3       3
#> 3       70        1      2     82      3       2       2       1       4
#> 4      168        1      2     67      4       4       1       3       1
#> 5      168        2      2     84      4       3       2       1       2
#> 6       16        2      2     85      4       2       2       3       3
#> 7      161        1      1     74      4       4       2       4       1
#> 8      110        4      2     87      4       3       2       2       1
#> 9       28        2      2     79      4       3       2       3       2
#> 10      40        2      2     83      4       3       2       1       2
#> # ... with 898 more rows, and 19 more variables: c86cop5 &lt;dbl>,
#> #   c87cop6 &lt;dbl>, c88cop7 &lt;dbl>, c89cop8 &lt;dbl>, c90cop9 &lt;dbl>,
#> #   c160age &lt;dbl>, c161sex &lt;dbl>, c172code &lt;dbl>, c175empl &lt;dbl>,
#> #   barthtot &lt;dbl>, neg_c_7 &lt;dbl>, pos_v_4 &lt;dbl>, quol_5 &lt;dbl>,
#> #   resttotn &lt;dbl>, tot_sc_e &lt;dbl>, n4pstu &lt;dbl>, nur_pst &lt;dbl>,
#> #   c82cop1_r &lt;dbl>, c83cop2_r &lt;dbl></pre>
<h2>sjmisc and dplyr</h2>
<p>The functions of <strong>sjmisc</strong> are designed to work together seamlessly with other packes from the tidyverse, like <strong>dplyr</strong>. For instance, you can use the functions from sjmisc both within a pipe-worklflow to manipulate data frames, or to create new variables with <code>mutate()</code>:</p>
<pre>efc %>% 
  select(c82cop1, c83cop2) %>% 
  rec(recodes = &quot;1,2=0; 3:4=2&quot;)
#> # A tibble: 908 × 2
#>    c82cop1_r c83cop2_r
#>        &lt;dbl>     &lt;dbl>
#> 1          2         0
#> 2          2         2
#> 3          0         0
#> 4          2         0
#> 5          2         0
#> 6          0         0
#> 7          2         0
#> 8          2         0
#> 9          2         0
#> 10         2         0
#> # ... with 898 more rows

efc %>% 
  select(c82cop1, c83cop2) %>% 
  mutate(
    c82cop1_dicho = rec(c82cop1, recodes = &quot;1,2=0; 3:4=2&quot;),
    c83cop2_dicho = rec(c83cop2, recodes = &quot;1,2=0; 3:4=2&quot;)
  ) %>% 
  head()
#>   c82cop1 c83cop2 c82cop1_dicho c83cop2_dicho
#> 1       3       2             2             0
#> 2       3       3             2             2
#> 3       2       2             0             0
#> 4       4       1             2             0
#> 5       3       2             2             0
#> 6       2       2             0             0</pre>
<h2>Final words</h2>
<p>I am trying to make my packages work more naturally together with other tidyverse-packages. From my experience, this philosophy makes absolutely sense (see <a target="_blank" rel="nofollow" href="https://github.com/tidyverse/tidyverse/blob/master/vignettes/manifesto.Rmd">tidyverse-manifesto</a>). If packages (and their functions) follow a certain logic (or „grammar“), it’s much easier to work with R and especially to switch to R from other statistical packages (to cite from the manifesto: „once you’ve mastered one [R package], you have a head start on mastering the others“). This meant that past and current updates of my packages introduced major changes in function design, most likely breaking existing code, but I think that after the latest updates of my packages, this progress is completed. Future updates probably mainly target enhancements or new functions, but do not mean major revisions of function designs.</p>
<p> Tagged: <a target="_blank" rel="nofollow" href="https://strengejacke.wordpress.com/tag/r/">R</a>, <a target="_blank" rel="nofollow" href="https://strengejacke.wordpress.com/tag/rstats/">rstats</a>, <a target="_blank" rel="nofollow" href="https://strengejacke.wordpress.com/tag/sjmisc/">sjmisc</a>, <a target="_blank" rel="nofollow" href="https://strengejacke.wordpress.com/tag/tidyverse/">tidyverse</a> <a target="_blank" rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/strengejacke.wordpress.com/1229/"><img alt="" src="http://feeds.wordpress.com/1.0/comments/strengejacke.wordpress.com/1229/" border="0"></a> <img alt="" src="https://i1.wp.com/pixel.wp.com/b.gif?resize=1%2C1&ssl=1" border="0" data-recalc-dims="1"></p>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://strengejacke.wordpress.com/2017/02/08/data-wrangling-within-the-tidyverse-the-design-philosophy-behind-the-sjmisc-package-rstats/"> R – Strenge Jacke!</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/1KxS5aT1ONU"></a></div>