title: R: Using plyr to perform fuzzy string matching between matching subsets of two data sources
body: <p>Say I have a list of counties with varying amounts of spelling errors or other issues that differentiate them from the <a href="http://www2.census.gov/geo/docs/reference/codes/files/national_county.txt" rel="nofollow">2010 FIPS dataset</a> (code to create <code>fips</code> dataframe below), but the states in which the misspelled counties reside are entered correctly. Here's a <code>sample</code> of 21 random observations from my full dataset:</p>
  
  <pre><code>tomatch &lt;- structure(list(county = c("Beauregard", "De Soto", "Dekalb", "Webster",
                                       "Saint Joseph", "West Feliciana", "Ketchikan Gateway", "Evangeline", 
                                       "Richmond City", "Saint Mary", "Saint Louis City", "Mclean", 
                                       "Union", "Bienville", "Covington City", "Martinsville City", 
                                       "Claiborne", "King And Queen", "Mclean", "Mcminn", "Prince Georges"
  ), state = c("LA", "LA", "GA", "LA", "IN", "LA", "AK", "LA", "VA", 
               "LA", "MO", "KY", "LA", "LA", "VA", "VA", "LA", "VA", "ND", "TN", 
               "MD")), .Names = c("county", "state"), class = c("tbl_df", "data.frame"
               ), row.names = c(NA, -21L))
  
                county state
  1         Beauregard    LA
  2            De Soto    LA
  3             Dekalb    GA
  4            Webster    LA
  5       Saint Joseph    IN
  6     West Feliciana    LA
  7  Ketchikan Gateway    AK
  8         Evangeline    LA
  9      Richmond City    VA
  10        Saint Mary    LA
  11  Saint Louis City    MO
  12            Mclean    KY
  13             Union    LA
  14         Bienville    LA
  15    Covington City    VA
  16 Martinsville City    VA
  17         Claiborne    LA
  18    King And Queen    VA
  19            Mclean    ND
  20            Mcminn    TN
  21    Prince Georges    MD
  </code></pre>
  
  <p>I've used <code>adist</code> to create a fuzzy string matching algorithm that matches around 80% of my counties to the county names in <code>fips</code>. However, sometimes it will match two counties with similar spelling, but from different states (e.g., "Webster, LA" gets matched to "Webster, GA" rather than "Webster Parrish, LA"). </p>
  
  <pre><code>distance &lt;- adist(tomatch$county, 
                    fips$countyname, 
                    partial = TRUE)
  
  
  min.name &lt;- apply(distance, 1, min)
  
  matchedcounties &lt;- NULL  
  
  for(i in 1:nrow(distance)) {
  
    s2.i &lt;- match(min.name[i], distance[i, ])
    s1.i &lt;- i
  
    matchedcounties &lt;- rbind(data.frame(s2.i = s2.i,
                                        s1.i = s1.i,
                                        s1name = tomatch[s1.i, ]$county, 
                                        s2name = fips[s2.i, ]$countyname, 
                                        adist = min.name[i]),
                             matchedcounties)
  
  }
  </code></pre>
  
  <p>Therefore, <strong>I want to restrict fuzzy string matching of county to the correctly spelled versions with matching state.</strong> </p>
  
  <p>My current algorithm makes one big matrix which calculates standard Levenshtein distances between both sources and then selects the value with the minimum distance. </p>
  
  <p>To solve my problem, I'm guessing I'd need to create a function that could be applied to each 'state' group by <code>ddply</code>, but I'm confused as to how I should indicate that the group value in the <code>ddply</code> function should match another dataframe. A <code>dplyr</code> solution or solution using any other package would be appreciated as well.</p>
  
  <p>Code to create FIPS dataset:</p>
  
  <pre><code>download.file('http://www2.census.gov/geo/docs/reference/codes/files/national_county.txt',
                './nationalfips.txt')
  
  fips &lt;- read.csv('./nationalfips.txt', 
                   stringsAsFactors = FALSE, colClasses = 'character', header = FALSE)
  names(fips) &lt;- c('state', 'statefips', 'countyfips', 'countyname', 'classfips')
  
  # remove 'County' from countyname
  fips$countyname &lt;- sub('County', '', fips$countyname, fixed = TRUE)
  fips$countyname &lt;- stringr::str_trim(fips$countyname)
  </code></pre>