0

So, the following graph is the inspiration for this post.

Essentially, what I want to do is utilize my work's sales data to see which of our brands is selling the most in each US state - and have the brand image file in each respective state.

For instance, if the best-selling brand of food we sell in Utah is Nestle - then I want the Nestle logo in that state.

My data set looks like this:

State     Brand      Sales    %TTL
 AK       Nestle     $260      8%
 AL       Mars       $480      10%
 AZ       Coca Cola  $319      12%
 ...
 WY       Nestle     $200      25%

I have the image files from Google, but I have no idea how to make this work. I know there's the cartography package and I've been following guide - but it isn't really 1:1. I can't even get the sample code to execute because it says it can't find the online address

I don't want this done for me - but how do I start? I essentially want it to look like the map in the first image, but have it correspond with images of the brands we work with.

Tableau didn't really have an optimal solution and this was done in R originally, so I'm trying to replicate it, but it's been proving difficult.

Quinten
  • 35,235
  • 5
  • 20
  • 53
  • 1
    The link you posted shows how this is done. It seems your problem is that you are struggling to apply it with your own data and collection of images. The problem here is that we don't have those images, or that data, so we would have to create a mock example to show you how to do it. But this is what the linked example does already, so it's difficult to know what concrete help we can offer here. What would a good answer look like with the information you have provided? – Allan Cameron Jun 01 '22 at 17:53
  • I think the issue is understanding the PNG capabilities example from the link and applying it to, yes, my data and mapping. That hyperlink in the PNG example does not work and is not of the USA - so I'm trying to see where I can read and upload that shape. The next thing is the for loop - that also iterates over a link that is now nonexistent for images. The data I've provided is actually what is on my data sheet, but I don't know where to collectively put all the images together to iterate over them so it understands essentially that "AK is Nestle, so put the Nestle logo in the right spot" –  Jun 01 '22 at 17:57
  • Could you perhaps put the file paths as character strings in a column in your data frame? – Allan Cameron Jun 01 '22 at 18:00
  • Would there be a way to do that process that isn't as manual? For example, 30 of the 50 states are Nestle for instance. Is there a way to make it more quick? And also is there anything I need to look out for for sizing? I guess I understand your point though to iterate over the Excel sheet. Do you also know how to make the US map instead of the Africa map? –  Jun 01 '22 at 18:41
  • Hi, see here an updated version of the post using `rasterpic` (I am the author of both): https://dieghernan.github.io/202201_maps-flags/ – dieghernan Jun 02 '22 at 15:53

1 Answers1

0

Well, see here an adaptation:

  1. First you need to get a sf (a map ) of the US states. I use here USAboundaries but you can use whaterver you prefer.
  2. Note that I needed to fake your data. Use your own.
  3. Use rowwise() and switch() to add a column to your data with the url of the png
  4. On the loop, for each brand: select the corresponding state, create the image overlay and add the layer to the plot.

See here a reproducible example:

library(USAboundaries)
#> The USAboundariesData package needs to be installed.
#>  Please try installing the package using the following command: 
#>      install.packages("USAboundariesData", repos = "https://ropensci.r-universe.dev", type = "source")
library(sf)
#> Linking to GEOS 3.9.1, GDAL 3.2.1, PROJ 7.2.1; sf_use_s2() is TRUE
library(tidyverse)
library(rasterpic)
library(tidyterra)

# Part 1: The map
states <- USAboundaries::states_contemporary_lores %>%
  select(State = state_abbr) %>%
  # Filter AK and HW
  filter(!(State %in% c("AK", "HI", "PR"))) %>%
  st_transform("ESRI:102003") 

states
#> Simple feature collection with 49 features and 1 field
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: -2356114 ymin: -1338125 xmax: 2258154 ymax: 1558935
#> Projected CRS: USA_Contiguous_Albers_Equal_Area_Conic
#> First 10 features:
#>    State                       geometry
#> 1     CA MULTIPOLYGON (((-2066285 -2...
#> 2     WI MULTIPOLYGON (((708320.1 91...
#> 3     ID MULTIPOLYGON (((-1673882 95...
#> 4     MN MULTIPOLYGON (((-91052.17 1...
#> 5     IA MULTIPOLYGON (((-50588.83 5...
#> 6     MO MULTIPOLYGON (((19670.04 34...
#> 7     MD MULTIPOLYGON (((1722285 240...
#> 8     OR MULTIPOLYGON (((-2285910 94...
#> 9     MI MULTIPOLYGON (((882371.5 99...
#> 10    MT MULTIPOLYGON (((-1474367 14...

# Base map
plot <- ggplot(states) +
  geom_sf(fill = "grey90") +
  theme_minimal() +
  theme(panel.background = element_rect(fill = "lightblue"))

plot

# Part 2: your data (I have to fake it)
# Use here your own data

# Assign 3 random brands
brands <- data.frame(State = states$State)
set.seed(1234)

brands$Brand <- sample(c("Nestle", "Mars", "Coca Cola"), nrow(brands), replace = TRUE)

# Part 3: find your pngs
logos <- brands %>%
  rowwise() %>%
  mutate(png = switch(Brand,
    "Nestle" = "https://1000marcas.net/wp-content/uploads/2020/01/Logo-Nestle.png",
    "Mars" = "https://1000marcas.net/wp-content/uploads/2020/02/Logo-Mars.png",
    "Coca Cola" = "https://w7.pngwing.com/pngs/873/613/png-transparent-world-of-coca-cola-fizzy-drinks-diet-coke-coca-cola-text-logo-cola.png",
    "null"
  ))

# Now loop
for (i in seq_len(nrow(logos))) {
  logo <- logos[i, ]
  shape <- states[states$State == logo$State, ]

  img <- rasterpic_img(shape, logo$png, mask = TRUE)

  plot <- plot + geom_spatraster_rgb(data = img)
}

plot

Created on 2022-06-03 by the reprex package (v2.0.1)

dieghernan
  • 2,690
  • 8
  • 16
  • Thank you for your help - one issue I'm running into is "Error: [as,sf] coercion failed. You can try coercing via a Spatial* (sp) class." Would you know what's going wrong? The main changes I've made are as follows: teams <- data.frame(State = January$ShipState) teams$Team <- data.frame(Team = January$Team) and ... for (i in seq_len(nrow(logos))) { logo <- logos[i, ] shape <- states[states$State == logo$State, ] img <- rasterpic_img(shape, logo$png, mask = TRUE) plot <- plot + geom_spatraster_rgb(data = img) } plot The rest - minus data + pngs are same –  Jun 08 '22 at 03:58
  • In this case I'm just using January month data and am using sports teams instead of brand names. –  Jun 08 '22 at 03:58
  • I have since fixed to all but one issue...."Error in png::readPNG(img) : file is not in PNG format." However - all images I used are png addresses –  Jun 08 '22 at 05:26
  • Final update - I got images onto the map, but its huge. It doesn't obey state lines. I did get one warning "In is.unit(x) : reached elapsed time limit." However, something is now outputting at least - it's just massive and unusable. Any advice? So sorry for blowing this up...first time doing a project of this difficulty –  Jun 08 '22 at 05:47
  • https://stackoverflow.com/questions/72540753/logo-plots-on-us-map-in-r-are-way-too-large –  Jun 08 '22 at 06:00
  • Really on the loop you just need to ensure that you are selecting the right county with the right png file. Please check using a single county and maybe recheck how you are integrating your data. For better answer next time include a sample of your data – dieghernan Jun 08 '22 at 16:42
  • Sample of data is included now on the other question you commented on. Any help is really appreciated. –  Jun 08 '22 at 16:46