Home > Mobile >  See unmatched countries for joinCountryData2Map in rworldmap?
See unmatched countries for joinCountryData2Map in rworldmap?

Time:05-21

I'm using the joinCountryData2Map function in rworldmap to match my data to the countries in the world map.

I get this result:

230 codes from your data successfully matched countries in the map
11 codes from your data failed to match with a country code in the map
11 codes from the map weren't represented in your data

I cannot figure out how to view those two lists of 11 countries. I am guessing that those 11 countries have issues with their ISO2 codes that I need to correct, but am not sure which ones to check without being able to view those two lists.

I'm guessing there's a solution along the lines of just View(SomeObject$Countries) but I haven't been able to find anything that works.

CodePudding user response:

Set joinCountryData2Map(...,verbose=TRUE) to print the names of the countries that failed to match in the console.

From the FAQ: "You can see that a summary of how many countries are successfully joined is output to the console. You can specify verbose=TRUE to get a full list of countries"

library(rworldmap)

data(countryExData)

# Set Angola to fail
countryExData[countryExData$ISO3V10 == "AGO", "ISO3V10"] <- "AGO_FAIL"

# Attempt to join
# With verbose=TRUE, failed joins (ie Angola) are printed in the console
sPDF <- joinCountryData2Map(
  countryExData[,c("ISO3V10", "Country")],
  joinCode = "ISO3",
  nameJoinColumn = "ISO3V10",
  verbose = TRUE)

# > 148 codes from your data successfully matched countries in the map
# > 1 codes from your data failed to match with a country code in the map
# >      failedCodes failedCountries
# > [1,] "AGO_FAIL"  "Angola"       
# > 95 codes from the map weren't represented in your data

But what if you want to get the information on failed joins programmatically? I may have missed something, but I don't see an option for that (i.e., str(sPDF) or function arguments). However, looking at the internals of joinCountryData2Map(), the object failedCountries contains the info you want, so it should be easy enough to include it in the returned object.

Here's how you could modify joinCountryData2Map() to return a list with two elements: the first element is the default object, and the second element is failedCountries.

# Modify the function to return the failed joins in the environment
joinCountryData2Map_wfails <- function(
  dF, joinCode = "ISO3", nameJoinColumn = "ISO3V10",
  nameCountryColumn = "Country", suggestForFailedCodes = FALSE, 
  mapResolution = "coarse", projection = NA, verbose = FALSE) {
  
  # Retain successful join as first element and failed join as second element
  ll <- list() # MODIFIED
  mapWithData <- getMap(resolution = mapResolution)
  if (!is.na(projection)) 
    warning("the projection argument has been deprecated, returning Lat Lon, use spTransform from package rgdal as shown in help details or the FAQ")
  listJoinCodesNew <- c("ISO_A2", "ISO_A3", "FIPS_10_", 
                        "ADMIN", "ISO_N3")
  listJoinCodesOld <- c("ISO2", "ISO3", "FIPS", 
                        "NAME", "UN")
  listJoinCodes <- c(listJoinCodesOld, listJoinCodesNew)
  if (joinCode %in% listJoinCodes == FALSE) {
    stop("your joinCode (", joinCode, ") in joinCountryData2Map() is not one of those supported. Options are :", 
         paste(listJoinCodes, ""), "\n")
    return(FALSE)
  }
  joinCodeOld <- joinCode
  if (joinCode %in% listJoinCodesOld) {
    joinCode <- listJoinCodesNew[match(joinCode, listJoinCodesOld)]
  }
  if (is.na(match(nameJoinColumn, names(dF)))) {
    stop("your chosen nameJoinColumn :'", nameJoinColumn, 
         "' seems not to exist in your data, columns = ", 
         paste(names(dF), ""))
    return(FALSE)
  }
  dF[[joinCode]] <- as.character(dF[[nameJoinColumn]])
  dF[[joinCode]] <- gsub("[[:space:]]*$", "", dF[[joinCode]])
  if (joinCode == "ADMIN") {
    dF$ISO3 <- NA
    for (i in 1:nrow(dF)) dF$ISO3[i] = rwmGetISO3(dF[[joinCode]][i])
    joinCode = "ISO3"
    nameCountryColumn = nameJoinColumn
  }
  matchPosnsInLookup <- match(as.character(dF[[joinCode]]), 
                              as.character(mapWithData@data[[joinCode]]))
  failedCodes <- dF[[joinCode]][is.na(matchPosnsInLookup)]
  numFailedCodes <- length(failedCodes)
  numMatchedCountries <- nrow(dF) - numFailedCodes
  cat(numMatchedCountries, "codes from your data successfully matched countries in the map\n")
  failedCountries <- dF[[nameCountryColumn]][is.na(matchPosnsInLookup)]
  failedCountries <- cbind(failedCodes, failedCountries = as.character(failedCountries))
  cat(numFailedCodes, "codes from your data failed to match with a country code in the map\n")
  if (verbose) 
    print(failedCountries)
  matchPosnsInUserData <- match(as.character(mapWithData@data[[joinCode]]), 
                                as.character(dF[[joinCode]]))
  codesMissingFromUserData <- as.character(mapWithData@data[[joinCode]][is.na(matchPosnsInUserData)])
  countriesMissingFromUserData <- as.character(mapWithData@data[["NAME"]][is.na(matchPosnsInUserData)])
  numMissingCodes <- length(codesMissingFromUserData)
  cat(numMissingCodes, "codes from the map weren't represented in your data\n")
  mapWithData@data <- cbind(mapWithData@data, dF[matchPosnsInUserData, 
  ])
  invisible(mapWithData)
  
  ll[[1]] <- mapWithData # MODIFIED
  ll[[2]] <- failedCountries # MODIFIED
  return(ll) # MODIFIED
}

Usage:

sPDF_wfails <- joinCountryData2Map_wfails(
  countryExData[,c("ISO3V10", "Country")],
  joinCode = "ISO3",
  nameJoinColumn = "ISO3V10",
  verbose = TRUE)

# This is the result of the original function
# sPDF_wfails[[1]]

# This is info on the failed joins
sPDF_wfails[[2]]

# >     failedCodes failedCountries
# > [1,] "AGO_FAIL"  "Angola" 
  • Related