Home > OS >  How merge specific states together by group with one label in ggplot2 in R?
How merge specific states together by group with one label in ggplot2 in R?

Time:06-22

I want to plot Electric grid map for U.S. So I need to merge specific states together . I want to plot border for those state together but it not working. Also just one label per each group. This is my data : [https://iastate.box.com/s/12xru62lvmbbkrohsn7b4wwexq11umn7] This is my code:

# Join and arrange
 states <- us_map(exclude = c("AK", "HI"))
 states_data <- left_join(states, myinput, by = c("abbr" = "region")) |> 
 arrange(emission, growth, group, order)

ggplot(states_data, aes(x, y, fill = value, group = group, subgroup = grid))  
geom_polygon() 
scale_fill_continuous(low = "white", high = "red", name = "Ele gen (EJ)", label = 
scales::comma)  
facet_grid(emission~growth)  
coord_equal()  
ggthemes::theme_map()  
theme(legend.position = "bottom") 
geom_text(aes(x, y, label = grid),size = 5,family = "serif",
        data = states_data, vjust = 1.2, nudge_y = -100000,check_overlap = T) 
geom_polygon(aes(color = "Border", group=grid),fill = NA,color = "black")

And this the output which is not what I have in my mid: enter image description here

I want to plot these regions (plus borders to specify because I can't show them with different color) enter image description here

CodePudding user response:

I couldn't find an overly simple way of making this happen, but I can help you make it happen.

First, I calculated the median x and y for each of the groups and facets.

mm <- states_data %>% 
  group_by(growth, emission, grid) %>% 
  summarise(x = median(x), y = median(y))

Then I looked for the closest line row of data that matched these coordinates for placing the label. I created a function, a vector of NA (to be updated), and then went through each of the medians to find the corresponding row in the data (states_data). This creates another column for the data, but the grid strings are only in the rows that were identified as the quasi-center of each grid.

mdist <- function(mm, df1) { #vector mm contains medians; df1 contains points to compare
  x = mm$x
  y = mm$y
  df2 <- df1 %>% mutate(rn = 1:nrow(.)) %>% 
    filter(grid == mm$grid, growth == mm$growth, emission == mm$emission)
  df3 <- data.frame(V1 = sqrt((abs(df2$x) - abs(x))^2   (abs(df2$y) - abs(y))^2),
                    rn = df2$rn,
                    grid = mm$grid) %>% 
    filter(V1 == min(V1))
  return(df3[1, ])
}

arr <- rep(NA, nrow(states_data))
invisible(
  map(1:nrow(mm),
      function(j) {
        gimme <- mdist(mm[j, ], states_data)
        arr[gimme$rn] <<- gimme$grid
      }))

Now, this column grid2 is used for the labels.

I noticed that you have group and subgroup in your call for ggplot. However, your subgroup has more divisions than group, that's what's causing the scribbling (for lack of a better word). This is what I mean:

enter image description here enter image description here

I switched the group/subgroup calls in ggplot for this reason. (You may have wanted that, so I just wanted to explain what and why I did what I did.)

I also noticed that your grid is on top of the text and the same color, which sort of drowns out the words. You used nudge_y, but I think you might get a bit more bang with hjust, as well.

enter image description here

This is what I used:

ggplot(states_data, aes(x, y, fill = value, subgroup = group, group = grid))  
  geom_polygon() 
  scale_fill_continuous(low = "white", high = "red", name = "Ele gen (EJ)", label = 
                          scales::comma)  
  facet_grid(emission~growth)  
  coord_equal()  
  ggthemes::theme_map()  
  theme(legend.position = "bottom")  
  geom_polygon(aes(color = "Border", group = grid),fill = NA, color = "lightgray")  
  geom_text(aes(label = grid2),size = 4, family = "serif", fontface = "bold",
            data = states_data, vjust = 1.2, hjust = .5, check_overlap = T)

enter image description here

It's not perfect. You're right-most labels are still running off the "page". However, this should get you going in the right direction.

CodePudding user response:

Similarly to the thread ggplot centered names on a map, you can use the ggh4x package for that.

library(ggh4x)
#> Loading required package: ggplot2
library(dplyr)

myinput <- readxl::read_excel("your data path")
states <- usmap::us_map(exclude = c("AK", "HI"))
states_data <- left_join(states, myinput, by = c("abbr" = "region")) |> 
  arrange(emission, growth, group, order)

## changing the group and subgroup
ggplot(states_data, aes(x, y, fill = value, group = grid, subgroup = group))  
  geom_polygon() 
  scale_fill_continuous(low = "white", high = "red", name = "Ele gen (EJ)", label = 
                          scales::comma)  
  facet_grid(emission~growth)  
  coord_equal()  
  ggthemes::theme_map()  
  ## using ggh4x
  stat_midpoint(aes(label = grid), geom = "text", size=2, check_overlap = T)  
  theme(legend.position = "bottom") 
  geom_polygon(aes(color = "Border", group=grid),fill = NA,color = "black")

  • Related