title: re-programming a semi-advanced rounding program
body: <p>Hi all: I have a question related to a previous post about a rounding program (available here:  <a href="https://stackoverflow.com/questions/25829504/r-round-the-contents-within-each-row-so-that-the-row-total-is-equal-to-a-number">R: Round the contents within each row so that the row total is equal to a number I specify</a>).</p>
  
  <p>The program is designed to round the contents within each row so that the row total is equal to a number I specify. Copied from the original post, here is a MWE that works:</p>
  
  <pre><code>Round &lt;- function(x, target) {
  r.x &lt;- round(x)
  diff.x &lt;- round(x) - x
  if ((s &lt;- sum(r.x)) == target) {
  return(r.x)
  } else if (s &gt; target) {
  select &lt;- seq(along=x)[diff.x &gt; 0]
  which &lt;- which.max(diff.x[select])
  x[select[which]] &lt;- r.x[select[which]] - 1
  Round(x, target)
  } else {
  select &lt;- seq(along=x)[diff.x &lt; 0]
  which &lt;- which.min(diff.x[select])
  x[select[which]] &lt;- r.x[select[which]] + 1
  Round(x, target)
  }
  }
  
  dat &lt;- read.table(header = TRUE, row.names = paste0('place', 1:4),
                text="race1 race2 total
                      1.2  2.1  3.4
                      3.4  3.6  7.0
                      7.7  0.8  8.5
                      5.3  1.4  6.7")
  
  totals &lt;- c(4.0, 7.0, 8.0, 7.0)
  
  do.call(rbind, lapply(1:nrow(dat), function(x) Round(dat[x, -3], totals[x])))
  
  #        race1 race2
  # place1     2     2
  # place2     3     4
  # place3     7     1
  # place4     5     2
  </code></pre>
  
  <p>The problem is this: It has recently come to my attention that this function ceases to work if the number the row is supposed to be rounded to is greater or less than 1 away from the natural rounded total. So, in the above example, row 2 is naturally rounded to 3 and 4. If the total specified in the totals object is equal to 6 through 8 for row 2, the function works fine. But if the total the row is coerced to is less than 6 or greater than 8, the function no longer works.</p>
  
  <p>To illustrate this example, the above 'Round' code no longer works if we change the totals values as follows:</p>
  
  <pre><code>dat &lt;- read.table(header = TRUE, row.names = paste0('place', 1:4),
                text="race1 race2 total
                      1.2  2.1  3.4
                      3.4  3.6  7.0
                      7.7  0.8  8.5
                      5.3  1.4  6.7")
  
  totals &lt;- c(4.0, 5.0, 8.0, 7.0)
  
  do.call(rbind, lapply(1:nrow(dat), function(x) Round(dat[x, -3], totals[x])))
  Error in data.frame(value, row.names=rn, check.names = FALSE, check.rows
  = FALSE) : 'row.names' should specify one of the variables
  </code></pre>
  
  <p>(Note the change in the totals object from c(4.0, 7.0,...) to c(4.0, 5.0,...))</p>
  
  <p>What I need help with is altering the code so that the special Rounding function will still work if the row total the row is forced to be rounded to is, say, 4 away from the natural rounded total. (In some cases in my more advanced data.frame I have rows which need to be rounded to up to 14 digits away from the naturally rounded row total.)</p>
  
  <p><strong>Updated Example</strong></p>
  
  <p>Using a slightly altered code provided by rawr, I now get an error if the total I need the row to be rounded to is 3 or more away from the natural rounded total. </p>
  
  <p>The updated code is as follows:</p>
  
  <pre><code>Round &lt;- function(x, target){
   r.x &lt;- round(x)
   diff.x &lt;- round(x) - x
   if ((s &lt;- sum(r.x)) == target) {return(r.x)
  } else if (s &gt; target) {
       select &lt;- seq(along=x)[diff.x != 0]
       which &lt;- which.max(diff.x[select])
       x[select[which]] &lt;- r.x[select[which]] - 1
       Round(x, target)
   }
   else{
       select &lt;- seq(along=x)[diff.x != 0]
       which &lt;- which.min(diff.x[select])
       x[select[which]] &lt;- r.x[select[which]] + 1
       Round(x, target)
   }
  }
  </code></pre>
  
  <p>And here is the example that is producing an error:</p>
  
  <pre><code>dat &lt;- read.table(header = TRUE, row.names = paste0('district', 1:4),
  text="race1 race2 total
  1.2 2.1 3.4
  3.4 3.6 7.0
  7.7 0.8 8.5
  5.3 1.4 6.7")
  
  totals &lt;- c(4.0, 5.0, 12.0, 7.0)
  
  do.call(rbind, lapply(1:nrow(dat), function(x) Round(dat[x, -3], totals[x])))
  
  Error in data.frame(value, row.names = rn, check.names = FALSE, check.rows = FALSE) : 
  'row.names' should specify one of the variables
  </code></pre>