title: Can I use separate() or extract() from tidyr to split a numeric value of variable length into its component digits?
body: <p>I have a data frame with ~300 observations, each associated with a numeric code that I want to split into its component digits. The code variable is either a 3 or 4 digit integer, aligned by its last digit, &amp; so my desired output would look something like this:</p>
  
  <pre><code>code    d4 d3 d2 d1
   403  &lt;NA&gt;  4  0  3 
  5123     5  1  2  3
   105  &lt;NA&gt;  1  0  5    
  </code></pre>
  
  <p>While I can see lots of ways to divide the code using <code>strsplit</code> (base R) or <code>stringr::str_split</code>,  I am having difficulty applying any of these operations to my data frame.</p>
  
  <pre><code>library(stringr)
  as.integer(unlist(str_split(5123, ""))[1]) # returns 5, the first digit - correct
  as.integer(rev(unlist(str_split(5123, "")))[1]) # returns 3, the last digit - correct
  </code></pre>
  
  <p>But the plausible (to me) operation</p>
  
  <pre><code>libray(dplyr)
  df &lt;- data.frame(code = c(403, 5123, 105))
  df &lt;- df %&gt;% 
    mutate(
      last = as.integer(rev(unlist(str_split(df$code,"")))[4])
    )
  </code></pre>
  
  <p>returns</p>
  
  <pre><code>&gt; df
    code last
  1  403    3
  2 5123    3
  3  105    3
  </code></pre>
  
  <p>Clearly my understanding of how operations on lists and atomic vectors are handled within data frames is lacking...     </p>
  
  <p>I then felt sure that either the <code>separate()</code> or <code>extract()</code> functions from the <code>tidyr</code> package would help. Certainly, <code>tidyr::separate()</code> produces the desired result if the codes are supplied as strings with a leading space before each digit: </p>
  
  <pre><code>library(tidyr)
  dfsep &lt;- data.frame(code = c(" 4 0 3", "5 1 2 3", " 1 0 5"))
  dfsep &lt;- dfsep %&gt;% 
    separate(
      code, c("d4", "d3", "d2", "d1"), fill =  "right", remove = FALSE
      )
  
  dfsep
       code d4 d3 d2 d1
  1   4 0 3     4  0  3
  2 5 1 2 3  5  1  2  3
  3   1 0 5     1  0  5
  </code></pre>
  
  <p>But a continuous string of digits cannot be split in this way; and empty search patterns are not supported by <code>tidyr::separate()</code></p>
  
  <pre><code>df &lt;- data.frame(code = c(403, 5123, 105))
  df &lt;- df %&gt;% 
    separate(
      code, c("d4", "d3", "d2", "d1"), fill =  "right", remove = FALSE
    )
  
  df
    code   d4   d3   d2   d1
  1  403  403 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt;
  2 5123 5123 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt;
  3  105  105 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt;
  </code></pre>
  
  <p>While the problem with <code>tidyr::extract()</code> is that although it extracts the digits beautifully I have not been able to find a set of arguments that handles both 3 &amp; 4 digit integers:</p>
  
  <pre><code>dfext &lt;- data.frame(code = c(403, 5123, 105))
  dfext &lt;- dfext %&gt;% 
    extract(
      code, c("d4", "d3", "d2", "d1"), "(.)(.)(.)(.)", remove = FALSE
      ) 
  
  dfext
    code   d4   d3   d2   d1
  1  403 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt;
  2 5123    5    1    2    3
  3  105 &lt;NA&gt; &lt;NA&gt; &lt;NA&gt; &lt;NA&gt;
  </code></pre>
  
  <p>Perhaps I have not understood how to construct the correct regex code for my purpose...</p>
  
  <p>I have looked at related questions on StackOverflow including this one about <a href="https://stackoverflow.com/questions/26804641/using-separate-from-tidyr-with-different-length-vectors">separate()</a> and this one about <a href="https://stackoverflow.com/questions/28526124/extracting-values-from-column-using-tidyr">extract()</a>, but I could not see how to apply the answers to my own problem. The question <a href="https://stackoverflow.com/questions/28956264/separate-a-column-into-multiple-columns-using-tidyrseparate-with-sep">here</a> gives a solution for a variable with values of fixed length, not variable. </p>
  
  <p>Any help, tips or observations would be much appreciated!</p>
  
  <p>P.S. To give context, this is a data frame of dives in a diving competition. Every row represents one dive, a single observation with multiple grouping variables: name, age, sex, dive number (e.g. 1 of 5), board height, dive code, dive position, tariff, J1 award, J2 award, ... J5 award, total award (dropping highest &amp; lowest awards), &amp; score (total award multiplied by tariff). The codes are determined by <a href="http://www.fina.org/content/appendix-2-fina-table-degrees-difficulty-springboard" rel="nofollow noreferrer">FINA</a></p>