title: find missing entries - improve efficiency by eliminating nested loop
body: <p>I would like to eliminate nested loop used to create data in <code>m</code> inside the function. The <code>missing_entries()</code> function is trying to identify and return values of <code>col1</code> missing for groups in <code>col2</code>. Is there any alternative way to approach this problem in order to improve efficiency?</p>
  
  <pre><code>missing_entries &lt;- function( data, x, y )
  {
    # find missing entries in x for the group in y
    # by comparing other groups in y
    require( 'data.table' )
  
    # require class of data to be data.table
    stopifnot( "data.table" %in% class(data) ) 
  
    # the outer loop with i refers to each unique value of column y
    # the inner loop with j refers to all unique values of column y
    # except the value in i under current iteration
    uniq_col2 &lt;- unique( data[, get(y) ] )
    m &lt;- lapply( uniq_col2, function(i){
      lapply( setdiff( uniq_col2, i ), function( j ) {
        z &lt;- setdiff( data[ get(y) == i, get(x)], data[ get(y) == j, get(x)])
        if( length(z) &gt; 0 ){
          return( data.frame( v1 = z, v2 = j,
                              stringsAsFactors = FALSE ) )
        } else{
          return()
        }
      } )
    })
  
    # row bind
    m &lt;- lapply( m, function(k) {
      if(!is.null(k)) {
        rbindlist(l = k)
      }})
  
    # collect only not null data
    m &lt;- rbindlist( l = m[lapply(m, nrow) &gt; 0] )
    colnames( m ) &lt;- c( x, y )
  
    return( m )
  }
  
  # testing
  test_data &lt;- structure(list(cardnty = c("many", "many", "many", "many", "many", "many",
                                          "many", "many", "many", "many", "many", "many",
                                          "many", "many", "many", "many", "many", "many",
                                          "many", "many", "many", "many", "many", "many"), 
                              col1 = c(2L, 4L, 3L, 13L, 5L, 6L, 7L, 17L, 9L, 4L, 3L, 
                                             2L, 8L, 5L, 6L, 7L, 14L, 17L, 19L, 13L, 
                                             9L, 12L, 11L, 20L), 
                              N = c(599L, 43L, 111L, 12L, 11L, 5L, 4L, 
                                    8L, 2L, 72L, 230L, 617L, 13L, 58L, 19L, 9L, 
                                    5L, 3L, 2L, 1L, 11L, 1L, 1L, 1L), 
                              col2 = c("cat", "cat", "cat", "cat", "cat", 
                                     "cat", "cat", "cat", "cat", "dog",  
                                     "dog", "dog", "dog", 
                                     "dog", "dog", "dog", 
                                     "dog", "dog", "dog", 
                                     "dog", "dog", "dog",
                                     "dog", "dog" )), 
                         .Names = c("cardnty", "col1", "N", "col2"), 
                         row.names = c(NA, -24L),
                         class = "data.frame")
  
  require('data.table')
  setDT(test_data)
  results &lt;- missing_entries(data = test_data, x = "col1", y = "col2")
  setDF(results)
  
  test_results &lt;- structure(list(col1 = c(8L, 14L, 19L, 12L, 11L, 20L), 
                                 col2 = c("cat", "cat", "cat", "cat", "cat", "cat")), 
                            .Names = c("col1", "col2"),
                            row.names = c(NA, -6L), 
                            class = "data.frame")
  
  identical( results, test_results)
  # TRUE
  </code></pre>