title: Faster Way to Create a Subset within a Loop or Apply Function in R
body: <p>I'm new to R, so apologies in advance for bad form in my code.</p>
  
  <p>I'm trying to figure out the best way to go through a dataframe, row by row, and modify a value based on logic that references other columns within that row  or an entirely different dataframe. The issue is that the logic I'm using necessitates creating and subsetting a dataframe for each row to retrieve a minimum value. My real data set is 47000 rows and 15 columns, so creating 47,000 subsets is taking a long time.</p>
  
  <p>Here are sample datasets to help describe what I'm talking about.</p>
  
  <pre><code>df1 &lt;- data.frame('A' = c(rep("Beer", 2), rep("Chip", 2)), 'B' = c(NA, 3,
         NA,9), 'C' = 5:8, 'D' = NA)
  df2 &lt;- data.frame('Q' = c(rep("Beer", 2), rep("Chip", 2)), 'R' = 6:9, 'S' = 
         c(12, 15, 4, 18), 'T' = c(23, 45, 75, 34)) 
  </code></pre>
  
  <p>df1:</p>
  
  <pre><code>  A    B    C    D
   Beer  NA   5    NA
   Beer  3    6    NA
   Chip  NA   7    NA
   Chip  9    8    NA
  </code></pre>
  
  <p>df2:</p>
  
  <pre><code>  Q    R    S    T
   Beer  6    12    23
   Beer  7    15    45
   Chip  8    4     75
   Chip  9    18    34
  </code></pre>
  
  <p>This loop does what I want, namely checking whether a value is NA in column B or not, if it isn't then use that value in for column D, if it is NA then retrieve the minimum value from a filtered subset of df2. In the real use case I have other filtering conditions.</p>
  
  <pre><code>require(dplyr)
  
  for (i in 1:nrow(df1)) {
    if (!(is.na(df1$B[i]))) {
      df1$D[i] &lt;- df1$B[i]}
    else {x &lt;- filter(df2,  df1$A[i] == df2$Q)
        x &lt;- min(x$S)
        df1$D[i] &lt;- x
    }
  }
  </code></pre>
  
  <p>Everyone says to avoid loops in R, so I created this function using apply which also works (although is a little more difficult to follow):</p>
  
  <pre><code>FUNC &lt;- function(x) {
    apply(x, 1, function(y) {
      if (!(is.na(y[2]))) {
        y[4] &lt;- y[2]}
      else {z &lt;- filter(df2,  y[1] == df2$Q)
      z &lt;- min(z$S)
      y[4] &lt;- z}
    }
    )
  }
  
  df1$D &lt;- as.numeric(FUNC(df1))
  </code></pre>
  
  <p>Output:</p>
  
  <pre><code>     A    B    C    D
      Beer  NA   5    12
      Beer  3    6    3
      Chip  NA   7    4
      Chip  9    8    9
  </code></pre>
  
  <p>Aside question: is there a way to reference items in vector <code>y</code> by name instead of by index position?</p>
  
  <p>So is there a better way to do this?  Right now both methods take about 5-8 minutes to run through 47,000+ rows which seems long to me.  </p>