Home > Software engineering >  Add legend for every point on ggmap instead of a group variable
Add legend for every point on ggmap instead of a group variable

Time:03-24

I've got the following data frame:

df1 <- structure(list(City = c("Ahmadnagar", "Ahmedabad", "Akola", "Amaravati", 
"Aurangabad", "Belgaum", "Bellary", "Bengaluru", "Bhavnagar", 
"Bhiwandi", "Bhuj", "Bhusaval", "Bidar", "Bijapur", "Chanda", 
"Chikka Mandya", "Chirala", "Davangere", "Ghandinagar", "Gulbarga", 
"Guntur", "Hindupur", "Hospet", "Hubli", "Kagaznagar", "Kakinada", 
"Kalyan", "Khanapur", "Kolar", "Kolhapur", "Kurnool", "Latur", 
"Machilipatnam", "Malegaon Camp", "Mangalore", "Mumbai", "Mysore", 
"Nanded", "Nandyal", "Nasik", "Navsari", "Nellore", "Ongole", 
"Parbhani", "Porbandar", "Proddatur", "Pune", "Raichur", "Rajahmundry", 
"Rajkot", "Sangli", "Shimoga", "Surat", "Tirupati", "Vadodara", 
"Vishakhapatnam", "Vizianagaram"), State = c("Maharashtra", "Gujarat", 
"Maharashtra", "Maharashtra", "Maharashtra", "Karnataka", "Karnataka", 
"Karnataka", "Gujarat", "Maharashtra", "Gujarat", "Maharashtra", 
"Karnataka", "Karnataka", "Maharashtra", "Karnataka", "Andhra Pradesh", 
"Karnataka", "Gujarat", "Karnataka", "Andhra Pradesh", "Andhra Pradesh", 
"Karnataka", "Karnataka", "Andhra Pradesh", "Andhra Pradesh", 
"Maharashtra", "Maharashtra", "Karnataka", "Maharashtra", "Andhra Pradesh", 
"Maharashtra", "Andhra Pradesh", "Maharashtra", "Karnataka", 
"Maharashtra", "Karnataka", "Maharashtra", "Andhra Pradesh", 
"Maharashtra", "Gujarat", "Andhra Pradesh", "Andhra Pradesh", 
"Maharashtra", "Gujarat", "Andhra Pradesh", "Maharashtra", "Karnataka", 
"Andhra Pradesh", "Gujarat", "Maharashtra", "Karnataka", "Gujarat", 
"Andhra Pradesh", "Gujarat", "Andhra Pradesh", "Andhra Pradesh"
), Lat = c(19.094571, 23.025793, 20.709569, 20.933272, 19.880943, 
15.862643, 15.142049, 12.977063, 21.774455, 19.300229, 23.253972, 
21.043649, 17.913309, 16.827715, 19.950758, 12.545602, 15.823849, 
14.469237, 23.216667, 17.335827, 16.299737, 13.828065, 15.269537, 
15.349955, 19.331589, 16.960361, 19.243703, 21.273716, 13.137679, 
16.695633, 15.828865, 18.399487, 16.187466, 20.569974, 12.865371, 
18.987807, 12.292664, 19.160227, 15.477994, 19.999963, 20.85, 
14.449918, 15.503565, 19.268553, 21.641346, 14.7502, 18.513271, 
16.205459, 17.005171, 22.291606, 16.856777, 13.932424, 21.195944, 
13.635505, 22.299405, 17.704052, 18.11329), Long = c(74.738432, 
72.587265, 76.998103, 77.75152, 75.346739, 74.508534, 76.92398, 
77.587106, 72.152496, 73.058813, 69.669281, 75.785058, 77.530105, 
75.718988, 79.295229, 76.895078, 80.352187, 75.92375, 72.683333, 
76.83757, 80.457293, 77.491425, 76.387103, 75.138619, 79.466051, 
82.238086, 73.135537, 76.117376, 78.129989, 74.231669, 78.036021, 
76.584252, 81.13888, 74.515415, 74.842432, 72.836447, 76.638543, 
77.314971, 78.483605, 73.776887, 72.916667, 79.986967, 80.044541, 
76.770807, 69.600868, 78.548129, 73.849852, 77.35567, 81.777839, 
70.793217, 74.569196, 75.572555, 72.830232, 79.419888, 73.208119, 
83.297663, 83.397743)), class = c("grouped_df", "tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -57L), groups = structure(list(
    State = c("Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", 
    "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", 
    "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", 
    "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", "Andhra Pradesh", 
    "Gujarat", "Gujarat", "Gujarat", "Gujarat", "Gujarat", "Gujarat", 
    "Gujarat", "Gujarat", "Gujarat", "Karnataka", "Karnataka", 
    "Karnataka", "Karnataka", "Karnataka", "Karnataka", "Karnataka", 
    "Karnataka", "Karnataka", "Karnataka", "Karnataka", "Karnataka", 
    "Karnataka", "Karnataka", "Karnataka", "Maharashtra", "Maharashtra", 
    "Maharashtra", "Maharashtra", "Maharashtra", "Maharashtra", 
    "Maharashtra", "Maharashtra", "Maharashtra", "Maharashtra", 
    "Maharashtra", "Maharashtra", "Maharashtra", "Maharashtra", 
    "Maharashtra", "Maharashtra", "Maharashtra", "Maharashtra"
    ), City = c("Chirala", "Guntur", "Hindupur", "Kagaznagar", 
    "Kakinada", "Kurnool", "Machilipatnam", "Nandyal", "Nellore", 
    "Ongole", "Proddatur", "Rajahmundry", "Tirupati", "Vishakhapatnam", 
    "Vizianagaram", "Ahmedabad", "Bhavnagar", "Bhuj", "Ghandinagar", 
    "Navsari", "Porbandar", "Rajkot", "Surat", "Vadodara", "Belgaum", 
    "Bellary", "Bengaluru", "Bidar", "Bijapur", "Chikka Mandya", 
    "Davangere", "Gulbarga", "Hospet", "Hubli", "Kolar", "Mangalore", 
    "Mysore", "Raichur", "Shimoga", "Ahmadnagar", "Akola", "Amaravati", 
    "Aurangabad", "Bhiwandi", "Bhusaval", "Chanda", "Kalyan", 
    "Khanapur", "Kolhapur", "Latur", "Malegaon Camp", "Mumbai", 
    "Nanded", "Nasik", "Parbhani", "Pune", "Sangli"), .rows = structure(list(
        17L, 21L, 22L, 25L, 26L, 31L, 33L, 39L, 42L, 43L, 46L, 
        49L, 54L, 56L, 57L, 2L, 9L, 11L, 19L, 41L, 45L, 50L, 
        53L, 55L, 6L, 7L, 8L, 13L, 14L, 16L, 18L, 20L, 23L, 24L, 
        29L, 35L, 37L, 48L, 52L, 1L, 3L, 4L, 5L, 10L, 12L, 15L, 
        27L, 28L, 30L, 32L, 34L, 36L, 38L, 40L, 44L, 47L, 51L), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -57L), .drop = TRUE))

From which I'm generating a plot like this: enter image description here

Here's the code I've used:

india_centroid <- c(68.18625, 6, 97.41529, 37)  
req_zoom <- calc_zoom(Long, Lat, data = df1)
map_type = get_map(location = india_centroid, zoom = req_zoom, maptype = "roadmap")
p <- ggmap(map_type, extent = "panel", legend = "bottomright", size = c(500, 600))
p   geom_point(aes(x = Long, y = Lat, color = State), data = df1)  
  ggtitle("Cities in India") 

So, as you can see the points are color based on the State column. And legend shows the names of the states they belong to. But, I need the legend to show the name of every City instead of the state while the colors are the same as per state.

I know that doesn't make sense because the colors will be repeated for the cities in the same state. But I need to know if it is possible. And if possible, how to achieve it.

CodePudding user response:

One option would be to create a named vector of colors which assigns to each City the State color. Doing so you could map City on the color aes and set the colors according to the color vector via scale_color_manual:

library(ggmap)
library(dplyr)

# State colors
col_state <- data.frame(
  State = sort(unique(df1$State)),
  color = scales::hue_pal()(length(unique(df1$State)))
)
# City colors
col_city <- df1 %>% 
  ungroup() %>% 
  select(City, State) %>% 
  distinct() %>% 
  left_join(col_state) %>% 
  select(-State) %>% 
  tibble::deframe()

india_centroid <- c(68.18625, 6, 97.41529, 37)  
req_zoom <- calc_zoom(Long, Lat, data = df1)
map_type = get_map(location = india_centroid, zoom = req_zoom, maptype = "roadmap")
p <- ggmap(map_type, extent = "panel", legend = "bottomright", size = c(500, 600))
p   geom_point(aes(x = Long, y = Lat, color = City), data = df1)  
  scale_color_manual(values = col_city)  
  ggtitle("Cities in India") 

enter image description here

EDIT To order the legend by State you have to set the breaks accordingly. To this I would suggest to rearrange you dataset by State and make use of forcats::fct_inorder to convert your City column to a factor. Afterwards you could set the breaks of the color scale according to the levels of the City factor:

df1 <- df1 %>% 
  arrange(State, City) %>% 
  mutate(City = forcats::fct_inorder(City))

p   geom_point(aes(x = Long, y = Lat, color = City), data = df1)  
  scale_color_manual(values = col_city, breaks = levels(df1$City))  
  ggtitle("Cities in India")

enter image description here

  • Related