Plot a table of separate data below a ggplot2 graph that lines up on the X axis

孤人 提交于 2021-02-18 18:11:00

问题


I'm looking to create a plot that contains a simple multi-line ggplot2 graph with a table of separate (but relevant) data below the graph that lines up by the X axis of the graph. The data table's column names do match the x axis of the graph (hours 1 to 24), but one column is dedicated to necessary row names.

Here are the graph and the data table separately:

Data table is cut off at hour 16 for brevity, but does extend to 24.

I've been attempting different solutions in gridExtra all morning adjusting different parameters like nrow, ncol, heights and widths, but the most simple solution is only one that produces a somewhat reasonable result. The code and image below is the best I have achieved:

library(gridExtra)

p1 <- ggplot(load_forecast_plot, aes(group=Load_Type, y=Load_Values, x=Hour,  colour = Load_Type)) + 
  geom_line(size = 1) +
  scale_x_continuous(breaks = c(1:24))

p1 <- ggplotGrob(p1)

p2<-tableGrob(df)

grid.arrange(p1, p2, top = paste("Load and Weather Error Power Grid", Sys.Date()-1, sep = " "))

grid.draw(tableGrob(MISO_wx_PrevDay_error_test,theme=ttheme_minimal(base_size = 5)))

Which produces:

I would like the graph to be larger while the table is smaller and aligned along the x axis as much as possible. I've looked into examples where the table is converted to a ggplot2 object, but those examples have data that is the same in the plot and table unlike mine.

Below is my data for a reproducible example. Any help is much appreciated! Thank you.

data for the ggplot graph:

dput(load_forecast_plot)
structure(list(Hour = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 
5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 
11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 
17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 
22, 22, 23, 23, 23, 24, 24, 24), Load_Type = c("Load", "DA_MTLF", 
"BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", 
"Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", 
"DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", 
"BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", 
"Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", 
"DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", 
"BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", 
"Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", 
"DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", 
"BC_MTLF", "Load", "DA_MTLF", "BC_MTLF", "Load", "DA_MTLF", "BC_MTLF"
), Load_Values = c(59141, 59260, 57862, 56493, 56470, 54964, 
54480, 54553, 52996, 53270, 53252, 51683, 53050, 52520, 50845, 
53020, 51723, 49627, 53844, 51907, 49293, 56956, 55069, 52700, 
60975, 60036, 58251, 65595, 65023, 63881, 69796, 69023, 68776, 
73392, 72517, 72591, 76412, 74896, 75452, 78454, 76538, 77547, 
79959, 77782, 79256, 81315, 78851, 80627, 82478, 79921, 81763, 
82638, 80027, 81896, 81244, 78906, 80328, 78484, 76627, 77304, 
77187, 75130, 75391, 74495, 72612, 72776, 69736, 68216, 68488, 
64844, 63756, 64145)), row.names = c(NA, -72L), class = c("tbl_df", 
"tbl", "data.frame"))

data table:

dput(df)
structure(list(WX_Error = c("CloudCover", "DewPoint", "RainFall", 
"SolarRadiation", "Temperature", "WindSpeed"), `1` = c("-13.72%", 
"-0.41°F", "0in", "0min", "-0.86°F", "0.26mph"), `2` = c("-8.52%", 
"-0.05°F", "-0.01in", "0min", "-1.2°F", "-0.11mph"), `3` = c("-9.22%", 
"-0.41°F", "-0.01in", "0min", "-1.26°F", "-1.41mph"), `4` = c("-14.57%", 
"-0.98°F", "-0.01in", "0min", "-1.48°F", "-0.99mph"), `5` = c("-15.81%", 
"-0.83°F", "-0.01in", "0min", "-0.83°F", "-1.58mph"), `6` = c("-13.43%", 
"-0.61°F", "0in", "-0.43min", "-0.46°F", "0.48mph"), `7` = c("-14.23%", 
"-0.28°F", "0in", "7.91min", "-1.15°F", "-0.43mph"), `8` = c("-2.29%", 
"0.1°F", "0in", "1.3min", "-0.72°F", "0.51mph"), `9` = c("-3.63%", 
"0.2°F", "0in", "1.96min", "-0.94°F", "-0.9mph"), `10` = c("4.73%", 
"0.25°F", "0in", "-2.99min", "-0.69°F", "0.25mph"), `11` = c("-8.68%", 
"0.8°F", "0.01in", "5.03min", "-0.83°F", "0.81mph"), `12` = c("-4.42%", 
"0.64°F", "0.01in", "2.34min", "-0.3°F", "0.9mph"), `13` = c("-15.06%", 
"0.49°F", "-0.01in", "8.08min", "0.29°F", "0.44mph"), `14` = c("-25.35%", 
"0.55°F", "-0.01in", "14.4min", "0.47°F", "0.59mph"), `15` = c("-19.36%", 
"0.6°F", "-0.01in", "10.76min", "0.44°F", "1.29mph"), `16` = c("-8.1%", 
"0.17°F", "-0.01in", "5.03min", "0.29°F", "1.26mph"), `17` = c("-21.01%", 
"-0.27°F", "-0.01in", "11.74min", "1.52°F", "0.72mph"), `18` = c("-22.84%", 
"-0.74°F", "-0.01in", "12.77min", "2.17°F", "1.34mph"), `19` = c("-18.57%", 
"-0.55°F", "0in", "10.35min", "0.46°F", "1.13mph"), `20` = c("-10.39%", 
"-0.91°F", "0.03in", "5.6min", "0.65°F", "0.71mph"), `21` = c("-6.65%", 
"-0.28°F", "0.06in", "1.66min", "-0.5°F", "-0.56mph"), `22` = c("-0.2%", 
"-0.4°F", "-0.01in", "0min", "-0.33°F", "-1.35mph"), `23` = c("4.39%", 
"0.11°F", "-0.01in", "0min", "-0.5°F", "-0.47mph"), `24` = c("-5.65%", 
"0.64°F", "0.01in", "0min", "-0.43°F", "0.35mph")), row.names = c(NA, 
-6L), groups = structure(list(Date = structure(c(18407, 18407, 
18407, 18407, 18407, 18407), class = "Date"), wx_vars = c("CloudCover", 
"DewPoint", "RainFall", "SolarRadiation", "Temperature", "WindSpeed"
), .rows = list(1L, 2L, 3L, 4L, 5L, 6L)), row.names = c(NA, -6L
), class = c("tbl_df", "tbl", "data.frame"), .drop = FALSE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

回答1:


You can format the table as a ggplot object and then use the patchwork package to take care of the alignment for you.

library(ggplot2)
library(patchwork)

p1 <- ggplot(load_forecast_plot, aes(group=Load_Type, y=Load_Values, x=Hour,  colour = Load_Type)) + 
  geom_line(size = 1) +
  scale_x_continuous(breaks = c(1:24))

p2 <- gridExtra::tableGrob(df)
# Set widths/heights to 'fill whatever space I have'
p2$widths <- unit(rep(1, ncol(p2)), "null")
p2$heights <- unit(rep(1, nrow(p2)), "null")

# Format table as plot
p3 <- ggplot() +
  annotation_custom(p2)

# Patchwork magic
p1 + p3 + plot_layout(ncol = 1)

I know it doesn't look great right now; you'd have to tinker with the device size and text size a bit more. But, the question was about the alignment and that seems OK.

EDIT:

You can match up the axis ticks with the columns too if you set the x-axis correctly:

p1 <- ggplot(load_forecast_plot, aes(group=Load_Type, y=Load_Values, x=Hour,  colour = Load_Type)) + 
  geom_line(size = 1) +
  scale_x_continuous(breaks = c(1:24),
                     limits = c(-1, 24),
                     expand = c(0,0.5))

or you could set the second column as axis text:

p1 <- ggplot(load_forecast_plot, aes(group=Load_Type, y=Load_Values, x=Hour,  colour = Load_Type)) + 
  geom_line(size = 1) +
  scale_x_continuous(breaks = c(1:24),
                     expand = c(0,0.5))

p2 <- gridExtra::tableGrob(df)[, -c(1:2)]
p2$widths <- unit(rep(1, ncol(p2)), "null")
p2$heights <- unit(rep(1, nrow(p2)), "null")

p3 <- ggplot() +
  annotation_custom(p2) +
  scale_y_discrete(breaks = rev(df$WX_Error), 
                   limits = c(rev(df$WX_Error), ""))

p1 + p3 + plot_layout(ncol = 1)

EDIT2:

I also didn't see any text size options, but here is how you could change the font size manually:

is_text <- vapply(p2$grobs, inherits, logical(1), "text")
p2$grobs[is_text] <- lapply(p2$grobs[is_text], function(text) {
  text$gp$fontsize <- 8
  text
})



回答2:


After a bit of fiddling around I got to this:

library(ggpubr)
p1 <- ggplot(load_forecast_plot, aes(group=Load_Type, y=Load_Values, x=Hour,  colour = Load_Type)) + 
  geom_line(size = 1) +
  scale_x_continuous(breaks = c(1:24)) +
  theme(legend.position="top")+
  theme(plot.margin=unit(c(0,1,0,3.1),"cm"))
p1


p2 <- ggtexttable(df)

plot <- ggarrange(p1, p2,
                  ncol = 1, nrow = 2,
                  heights = c(10,3))
plot

Just play around with the margin and the device size until it is more or less aligned. Is a bit of a workaround though and @teunbrand's solution that I just saw now looks more promising.



来源:https://stackoverflow.com/questions/62047359/plot-a-table-of-separate-data-below-a-ggplot2-graph-that-lines-up-on-the-x-axis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!