Why does dplyr error in this nested if_else, when logical condition means output should not be evaluated?
<p>I have a nested <code>if_else</code> statement inside <code>mutate</code>. In my example data frame:</p>

<pre><code>tmp_df2 &lt;- data.frame(a = c(1,1,2), b = c(T,F,T), c = c(1,2,3))

  a     b c
1 1  TRUE 1
2 1 FALSE 2
3 2  TRUE 3
</code></pre>

<p>I wish to group by <code>a</code> and then perform operations based on whether a group has one or two rows. I would have thought this nested <code>if_else</code> would suffice:</p>

<pre><code>tmp_df2 %&gt;%
    group_by(a) %&gt;%
    mutate(tmp_check = n() == 1) %&gt;%
    mutate(d = if_else(tmp_check, # check for number of entries in group
                       0,
                       if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
    )
    )
</code></pre>

<p>But this throws the error:</p>

<pre><code>Error in eval(substitute(expr), envir, enclos) : 
  `false` is length 2 not 1 or 1.
</code></pre>

<p>The way the example is set up, when the first <code>if_else(n() == 1)</code> condition evaluates to true, then one element is returned, but when it evaluates to false, then a vector with two elements is returned, which is what I am assuming is causing the error. Yet, logically this statement seems sound to me.</p>

<p>The following two statements produce (desired) results:</p>

<pre><code>&gt; tmp_df2 %&gt;%
+     group_by(a) %&gt;%
+     mutate(d = ifelse(rep(n() == 1, n()), # avoid undesired recycling
+                        0,
+                        if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
+     )
+     )
Source: local data frame [3 x 4]
Groups: a [2]

      a     b     c     d
  &lt;dbl&gt; &lt;lgl&gt; &lt;dbl&gt; &lt;dbl&gt;
1     1  TRUE     1   3.0
2     1 FALSE     2   1.5
3     2  TRUE     3   0.0
</code></pre>

<p>or just filtering so that only groups containing two rows are left:</p>

<pre><code>&gt; tmp_df2 %&gt;%
+     group_by(a) %&gt;%
+     filter(n() == 2) %&gt;%
+     mutate(d = if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)]))
Source: local data frame [2 x 4]
Groups: a [1]

      a     b     c     d
  &lt;dbl&gt; &lt;lgl&gt; &lt;dbl&gt; &lt;dbl&gt;
1     1  TRUE     1   3.0
2     1 FALSE     2   1.5
</code></pre>

<p>I have three questions. </p>

<ol>
<li><p>How does dplyr know that the second output that should not have been evaluated, due to the logical condition, is invalid?</p></li>
<li><p>How do I get the desired behaviour in dplyr (without using <code>ifelse</code>)?</p></li>
</ol>

<p><strong>EDIT</strong> as noted in an answer, either do not have the temporary <code>tmp_check</code> column and use the <code>if ... else</code> construct, or use the following code that works, but produces warnings:</p>

<pre><code>library(dplyr)
tmp_df2 %&gt;%
    group_by(a) %&gt;%
    mutate(tmp_check = n() == 1) %&gt;%
    mutate(d = if (tmp_check)  # check for number of entries in group
                       0 else
                       if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
    )
</code></pre>