R语言:实现表格上方自适应年份数量的动态标签求助
Hey Andy, let's fix up that table to have those smart, auto-adjusting labels you need! The goal is to make sure the "Production", "Forecast", and "Delta" headers automatically resize their width when you switch from 6 years to 3 (or any other number). Here's a step-by-step revamp of your code:
Step 1: Refine Data Merging (Flexible for Any Number of Years)
First, let's clean up the data processing part to automatically detect how many years you're working with, instead of hardcoding column indices:
# Load your data proddata <- read.table("C:/...Production.csv", sep=";", header=TRUE) forcdata <- read.table("C:...Forecast.csv", sep=";", header=TRUE) # Grab unique wells and auto-detect number of years (assuming "Well" is your identifier column) wells <- unique(proddata$Well) year_cols <- grep("Year", colnames(proddata)) # Use this if your year columns have "Year" in the name n_years <- length(year_cols) # Initialize empty dataframe for merged results mergedAll <- data.frame() # Loop through each well to combine production, forecast, and delta for (well in wells) { # Pull production/forecast data for the current well (only year columns) prod_w <- subset(proddata, Well == well)[, year_cols] forc_w <- subset(forcdata, Well == well)[, year_cols] # Calculate the delta (production minus forecast) delta_w <- prod_w - forc_w # Transform each dataset to a single row, then combine prod_row <- t(prod_w) forc_row <- t(forc_w) delta_row <- t(delta_w) merged_row <- cbind(prod_row, forc_row, delta_row) colnames(merged_row) <- c(colnames(prod_w), colnames(forc_w), colnames(delta_w)) rownames(merged_row) <- well # Add to the full merged table mergedAll <- rbind(mergedAll, merged_row) }
This part will automatically adapt if you add/remove year columns—no need to tweak indices manually!
Step 2: Add Adaptive Top Labels
Now we'll use grid and gridExtra to build header labels that resize with the number of years. Each label ("Production", "Forecast", "Delta") will span exactly the number of year columns in its group:
library(grid) library(gridExtra) # Define your header labels header_labels <- c("Production", "Forecast", "Delta") # Set width for each header group (each spans n_years columns) group_widths <- rep(n_years, 3) # Create the header grob (graphical object) header_grob <- tableGrob( matrix(header_labels, nrow = 1), theme = ttheme_minimal( core = list(fg_params = list(hjust = 0.5, x = 0.5)), colhead = list(fg_params = list(hjust = 0.5, x = 0.5)) ), widths = unit(group_widths, "null") # Auto-adjust width based on number of years ) # Create the main table grob main_table_grob <- tableGrob( mergedAll, theme = ttheme_minimal(), rows = rownames(mergedAll) ) # Combine header and table into one final grob final_table <- arrangeGrob( header_grob, main_table_grob, nrow = 2, heights = unit(c(1, 10), "null") # Adjust header height to look proportional ) # Draw the finished table grid.draw(final_table)
Key Bits That Make It Adaptive:
group_widths <- rep(n_years, 3): Ensures each header label spans exactly the number of year columns in its section. If you switch to 3 years, each label will automatically shrink to cover 3 columns instead of 6.- Using
unit(group_widths, "null")ties the header width directly to the table's column widths, so everything stays aligned.
If your year columns don't have "Year" in their names, just replace year_cols <- grep("Year", colnames(proddata)) with the exact indices (like year_cols <- 1:6 for 6 years) — the rest of the code will still work seamlessly.
内容的提问来源于stack exchange,提问作者Andy

