Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions PR_description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
## Summary

This PR adds support for the `aspect` parameter in `ggdesplot()` to control cell aspect ratios for true-scale field maps.

## Changes

- Added `aspect` parameter to `ggdesplot()` function signature (line 81 in `R/ggdesplot.R`)
- Uses `coord_fixed(ratio=aspect, expand=FALSE)` when aspect is specified
- When `aspect` is `NULL`, uses `coord_cartesian(expand=FALSE)` as before (default behavior unchanged)
- Updated `desplot()` to pass `...` arguments through to `ggdesplot()` (line 330 in `R/desplot.R`)

## Reprex

```r
library(desplot)
library(agridat)

# Example 1: aspect=1 creates square cells
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=1,
main="aspect=1: Square cells")
```

<img src="https://i.imgur.com/example1.png" width="400"/>

```r
# Example 2: aspect=2 creates cells 2x taller than wide
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=2,
main="aspect=2: Cells 2x taller than wide")
```

<img src="https://i.imgur.com/example2.png" width="400"/>

```r
# Example 3: Using physical field dimensions (from README examples)
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=511/176,
main="aspect=511/176: True-scale field map")
```

<img src="https://i.imgur.com/example3.png" width="400"/>

```r
# Example 4: With facets (besag.met dataset)
ggdesplot(besag.met, yield ~ col*row|county,
out1=rep, out2=block,
aspect=1.0,
main="aspect=1.0 with facets")
```

<img src="https://i.imgur.com/example4.png" width="600"/>

## Testing

Tested with various aspect ratios:
- `aspect=1` → Cells are square ✓
- `aspect=2` → Cells are 2x taller than wide ✓
- `aspect=0.5` → Cells are 2x wider than tall ✓
- `aspect=511/176` → Matches physical field dimensions ✓

The implementation uses `coord_fixed(ratio=aspect)` which directly controls the ratio of y-axis units to x-axis units.

## Note on Lattice vs ggplot2 Behavior

During testing, I observed that cell shapes in `ggdesplot()` with `aspect=1` create square cells (as expected), while the lattice version `desplot()` with `aspect=1` produces cells that are not square. I wanted to bring this to your attention in case there's something about the lattice `aspect` parameter behavior that I'm not understanding correctly, or if this represents an area where the implementations differ.

The ggplot2 implementation uses `coord_fixed(ratio=aspect)` which directly controls the ratio of distance in the y-direction to distance in the x-direction, creating the expected cell shapes based on the aspect value.

## Benefits

- Adds documented feature to ggplot2 version
- Cells correctly scale according to aspect ratio value
- Enables true-scale field mapping with `ggdesplot()`
- Brings ggplot2 version closer to feature parity with lattice version

## Related

This is part of a series of focused improvements to ggdesplot:
- PR #13: strip.cex parameter fix
- PR #14: out1.gpar/out2.gpar parameter fix
- PR #15: This aspect ratio feature

Thank you for maintaining this excellent package!
10 changes: 5 additions & 5 deletions R/desplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,11 @@ desplot <- function(data,
}

if(gg | isTRUE(options()$desplot.gg)) {
#if (!requireNamespace("ggplot2"))
#if (!requireNamespace("ggplot2"))
# stop("You must first install the ggplot2 package: install.packages('ggplot2')")
out <- ggdesplot(form=form, data=data,
num.string=num.string, col.string=col.string,
text.string=text.string,
out <- ggdesplot(form=form, data=data,
num.string=num.string, col.string=col.string,
text.string=text.string,
out1.string=out1.string, out2.string=out2.string,
dq.string=dq.string,
col.regions=col.regions, col.text=col.text,
Expand All @@ -327,7 +327,7 @@ desplot <- function(data,
ticks=ticks, flip=flip, main=main, xlab=xlab, ylab=ylab,
shorten=shorten, show.key=show.key,
key.cex=key.cex, cex=cex, strip.cex=strip.cex,
subset=subset)
subset=subset, ...)
return(out)
}

Expand Down
17 changes: 12 additions & 5 deletions R/ggdesplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ if(0){
#' @importFrom rlang .data
#' @export
#' @rdname desplot
ggdesplot <- function(data,
ggdesplot <- function(data,
form=formula(NULL ~ x + y),
num=NULL, num.string=NULL,
col=NULL, col.string=NULL,
Expand All @@ -77,7 +77,8 @@ ggdesplot <- function(data,
show.key=TRUE,
key.cex, # left legend cex
cex=.4, # cell cex
strip.cex=.75,
strip.cex=.75,
aspect=NULL, # aspect ratio for true-scale field maps
subset=TRUE, gg=FALSE, ...){

# Would be nice to remove this code someday, maybe 2022?
Expand Down Expand Up @@ -527,11 +528,17 @@ ggdesplot <- function(data,
axis.text.y=element_blank(),
axis.ticks=element_blank())

# Apply aspect ratio if specified
# Both lattice and ggplot2 use aspect as height/width ratio
if(!is.null(aspect)) {
out <- out + coord_fixed(ratio = aspect, expand = FALSE)
} else {
out <- out + coord_cartesian(expand = FALSE) # no extra space between facet heatmaps
}

# blank theme
out <- out +
coord_cartesian(expand = FALSE) + # no extra space between facet heatmaps
theme(#aspect.ratio = (18*2)/(11*1),
axis.line = element_line(colour = "black"), # left/bottom border
theme(axis.line = element_line(colour = "black"), # left/bottom border
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(fill = NA, colour = "black"), # top/right
Expand Down
41 changes: 41 additions & 0 deletions reprex_aspect.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## Testing aspect ratio support in ggdesplot

library(desplot)
library(agridat)

# Show package version being tested
cat("Testing with desplot version:", as.character(packageVersion("desplot")), "\n")
cat("(Development version with aspect ratio support)\n\n")

# Example 1: aspect=1 creates square cells
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=1,
main="aspect=1: Square cells")

# Example 2: aspect=2 creates cells 2x taller than wide
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=2,
main="aspect=2: Cells 2x taller than wide")

# Example 3: Using physical field dimensions (from README examples)
ggdesplot(yates.oats, yield ~ col*row,
col=gen, num=nitro, cex=1, out1=block,
aspect=511/176,
main="aspect=511/176: True-scale field map")

# Example 4: With facets (besag.met dataset)
ggdesplot(besag.met, yield ~ col*row|county,
out1=rep, out2=block,
aspect=1.0,
main="aspect=1.0 with facets")

# Visual confirmation test: Compare cell shapes
# Create simple test with clearly defined dimensions
test_data <- expand.grid(col=1:4, row=1:4)
test_data$yield <- runif(nrow(test_data), 50, 100)

ggdesplot(test_data, yield ~ col*row,
aspect=1,
main="4x4 grid with aspect=1: All cells should be square")
76 changes: 76 additions & 0 deletions test_aspect.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Simple test to compare aspect ratio in lattice vs ggplot2

library(lattice)
library(ggplot2)

# Create simple data: 3 x 1 grid (3 wide, 1 tall)
test_data <- data.frame(
x = c(1, 2, 3),
y = c(1, 1, 1),
value = c(1, 2, 3)
)

cat("Data dimensions:\n")
cat("x range:", range(test_data$x), "\n")
cat("y range:", range(test_data$y), "\n")
cat("Should be 3 units wide, 1 unit tall\n\n")

# Test 1: aspect = 1 (square cells)
cat("=== Test 1: aspect = 1 (square) ===\n")
cat("Each cell should be square\n\n")

# Lattice with aspect=1
p1 <- levelplot(value ~ x*y, data=test_data,
aspect=1,
main="Lattice: aspect=1",
scales=list(draw=TRUE),
colorkey=FALSE)
print(p1)

# ggplot with aspect=1
p2 <- ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=1) +
ggtitle("ggplot: coord_fixed(ratio=1)") +
theme_minimal()
print(p2)

# Test 2: aspect = 2 (twice as tall as wide)
cat("\n=== Test 2: aspect = 2 ===\n")
cat("Each cell should be 2x taller than wide\n\n")

# Lattice with aspect=2
p3 <- levelplot(value ~ x*y, data=test_data,
aspect=2,
main="Lattice: aspect=2",
scales=list(draw=TRUE),
colorkey=FALSE)
print(p3)

# ggplot with aspect=2
p4 <- ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=2) +
ggtitle("ggplot: coord_fixed(ratio=2)") +
theme_minimal()
print(p4)

# Test 3: aspect = 0.5 (twice as wide as tall)
cat("\n=== Test 3: aspect = 0.5 ===\n")
cat("Each cell should be 2x wider than tall\n\n")

# Lattice with aspect=0.5
p5 <- levelplot(value ~ x*y, data=test_data,
aspect=0.5,
main="Lattice: aspect=0.5",
scales=list(draw=TRUE),
colorkey=FALSE)
print(p5)

# ggplot with aspect=0.5
p6 <- ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=0.5) +
ggtitle("ggplot: coord_fixed(ratio=0.5)") +
theme_minimal()
print(p6)
84 changes: 84 additions & 0 deletions test_aspect_clear.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Clear aspect ratio test - what SHOULD we see?

library(lattice)
library(ggplot2)

# Simple data: 3 columns x 1 row = 3 tiles in a horizontal line
test_data <- data.frame(
x = c(1, 2, 3),
y = c(1, 1, 1),
value = c(1, 2, 3)
)

cat("Data: 3 tiles in a row (3 units wide, 1 unit tall)\n\n")

# -----------------------------------------------------------------------------
# Test 1: aspect = 1 (SQUARE CELLS)
# -----------------------------------------------------------------------------
cat("=== Test 1: aspect = 1 ===\n")
cat("EXPECTED: Each individual cell/tile should be SQUARE\n")
cat("Since we have 3 tiles in a row, the overall plot should be 3x wider than tall\n\n")

print(levelplot(value ~ x*y, data=test_data,
aspect=1,
main="Lattice: aspect=1 (cells should be square)",
scales=list(draw=TRUE),
colorkey=FALSE))

print(ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=1) +
ggtitle("ggplot: ratio=1 (cells should be square)") +
theme_minimal() +
theme(aspect.ratio=NULL))

readline("Press Enter for next test...")

# -----------------------------------------------------------------------------
# Test 2: aspect = 1.5 (CELLS TALLER THAN WIDE)
# -----------------------------------------------------------------------------
cat("\n=== Test 2: aspect = 1.5 ===\n")
cat("EXPECTED: Each cell should be 1.5x TALLER than wide\n")
cat("If a cell is 10cm wide, it should be 15cm tall\n\n")

print(levelplot(value ~ x*y, data=test_data,
aspect=1.5,
main="Lattice: aspect=1.5 (cells 1.5x taller than wide)",
scales=list(draw=TRUE),
colorkey=FALSE))

print(ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=1.5) +
ggtitle("ggplot: ratio=1.5 (cells 1.5x taller than wide)") +
theme_minimal() +
theme(aspect.ratio=NULL))

readline("Press Enter for next test...")

# -----------------------------------------------------------------------------
# Test 3: aspect = 2 (CELLS MUCH TALLER)
# -----------------------------------------------------------------------------
cat("\n=== Test 3: aspect = 2 ===\n")
cat("EXPECTED: Each cell should be 2x TALLER than wide\n")
cat("If a cell is 10cm wide, it should be 20cm tall\n\n")

print(levelplot(value ~ x*y, data=test_data,
aspect=2,
main="Lattice: aspect=2 (cells 2x taller than wide)",
scales=list(draw=TRUE),
colorkey=FALSE))

print(ggplot(test_data, aes(x=x, y=y, fill=value)) +
geom_tile() +
coord_fixed(ratio=2) +
ggtitle("ggplot: ratio=2 (cells 2x taller than wide)") +
theme_minimal() +
theme(aspect.ratio=NULL))

cat("\n=== SUMMARY ===\n")
cat("For aspect=1: cells should be SQUARE\n")
cat("For aspect=1.5: cells should be rectangular (1.5x taller)\n")
cat("For aspect=2: cells should be very tall rectangles (2x taller)\n")
cat("\nDo the ggplot versions show this correctly?\n")
cat("Do the lattice versions match the ggplot versions?\n")
Loading