Change length.out in ifelse function
<p>I'm running a simple ifelse function</p>

<pre><code>f &lt;- function(x) {
ifelse(x==shift(x), x + 0.001* sd(x, na.rm = TRUE), x)
}
</code></pre>

<p>where shift is from the data.table package</p>

<p>which allows me to change, for each column in a dataframe (usig <strong>apply</strong>), a value which is exactly the same as the previous one. The problem is that the ifelse function returns a length which is equal to the length of the test. In this case, the length is the one of <em>shift(x)</em> and not <em>x</em>. Therefore I end up with the first element (or the last, if using type = "lead", instead of the default "lag") of each column turned into NA.</p>

<p>Here a MWE:</p>

<pre><code>a &lt;- c(1,2,2,3,4,5,6)
b &lt;- c(4,5,6,7,8,8,9)
data &lt;- data.frame(cbind(a,b))
f &lt;- function(x) {
ifelse(x==shift(x), x + 0.001* sd(x, na.rm = TRUE), x)
}
apply(data, 2, f)
</code></pre>

<p>Therefore I thought I could change the <strong>ifelse</strong> function: I've done a few attempts to change the <strong>length.out</strong> but I haven't succeeded yet </p>

<pre><code>function (test, yes, no) 
{
if (is.atomic(test)) {
    if (typeof(test) != "logical") 
        storage.mode(test) &lt;- "logical"
    if (length(test) == 1 &amp;&amp; is.null(attributes(test))) {
        if (is.na(test)) 
            return(NA)
        else if (test) {
            if (length(yes) == 1 &amp;&amp; is.null(attributes(yes))) 
              return(yes)
        }
        else if (length(no) == 1 &amp;&amp; is.null(attributes(no))) 
            return(no)
    }
}
else test &lt;- if (isS4(test)) 
    methods::as(test, "logical")
else as.logical(test)
ans &lt;- test
ok &lt;- !(nas &lt;- is.na(test))
if (any(test[ok])) 
    ans[test &amp; ok] &lt;- rep(yes, length.out = length(ans))[test &amp; 
        ok]
if (any(!test[ok])) 
    ans[!test &amp; ok] &lt;- rep(no, length.out = length(ans))[!test &amp; 
        ok]
ans[nas] &lt;- NA
ans
}
</code></pre>

<p><strong>EDIT</strong></p>

<p>My original code was: </p>

<pre><code>copy &lt;- copy(data)
for (j in 1: ncol(copy)) {
    for (i in 2: nrow(copy)) {
        if (copy[i,j] == copy[i-1,j] &amp; !is.na(copy[i,j]) &amp; !is.na(copy[i-1,j]))  {
            copy[i,j] &lt;- copy[i-1,j] + (0.0001*sd(copy[,j], na.rm = T))
        }
    }
}
</code></pre>

<p>but using it with large matrices may cause slow running time. This deals with multiple repetitions. 
The goal was to get to a vectorised, quicker method using a function and apply.</p>