Interactive Pan/Zoom with Shared Axes in gggrid¶
When subplots in a gggrid share axes via sharex or sharey, interactive pan and zoom propagate across sibling plots. Zooming or panning one subplot automatically updates all plots sharing that axis.
Tip: double-click a subplot to reset it.
In [1]:
%useLatestDescriptors
%use dataframe
%use lets-plot
In [2]:
val df = DataFrame.readCSV("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/refs/heads/master/data/mpg2.csv")
val data = df.toMap()
val mpg = "miles per gallon"
val wt = "vehicle weight (lbs.)"
val origin = "origin of car"
val hp = "engine horsepower"
val accel = "time to accelerate (sec.)"
val displ = "engine displacement (cu. inches)"
df.head(3)
Out[2]:
DataFrame: rowsCount = 3, columnsCount = 9
| miles per gallon | number of cylinders | engine displacement (cu. inches) | engine horsepower | vehicle weight (lbs.) | time to accelerate (sec.) | model year | origin of car | vehicle name |
|---|---|---|---|---|---|---|---|---|
| 18,000000 | 8 | 307,000000 | 130 | 3504 | 12,000000 | 70 | US | chevrolet chevelle malibu |
| 15,000000 | 8 | 350,000000 | 165 | 3693 | 11,500000 | 70 | US | buick skylark 320 |
| 18,000000 | 8 | 318,000000 | 150 | 3436 | 11,000000 | 70 | US | plymouth satellite |
Shared X-axis (all)¶
In [3]:
val p1 = letsPlot(data) { x = mpg; y = wt } + geomPoint { color = origin } + ggtitle("Weight vs MPG")
val p2 = letsPlot(data) { x = mpg; y = hp } + geomPoint { color = origin } + ggtitle("HP vs MPG")
val p3 = letsPlot(data) { x = mpg; y = accel } + geomPoint { color = origin } + ggtitle("Accel vs MPG")
val p4 = letsPlot(data) { x = mpg; y = displ } + geomPoint { color = origin } + ggtitle("Displ vs MPG")
gggrid(listOf(p1, p2, p3, p4), ncol = 2, guides = "collect",
sharex = "all"
) + ggsize(800, 600) + ggtb()
Out[3]:
Shared Y-axis (all)¶
In [4]:
val p1 = letsPlot(data) { x = displ; y = mpg } + geomPoint { color = origin } + ggtitle("MPG vs Displ")
val p2 = letsPlot(data) { x = hp; y = mpg } + geomPoint { color = origin } + ggtitle("MPG vs HP")
val p3 = letsPlot(data) { x = wt; y = mpg } + geomPoint { color = origin } + ggtitle("MPG vs Weight")
val p4 = letsPlot(data) { x = accel; y = mpg } + geomPoint { color = origin } + ggtitle("MPG vs Accel")
gggrid(listOf(p1, p2, p3, p4), ncol = 2, guides = "collect",
sharey = "all"
) + ggsize(800, 600) + ggtb()
Out[4]:
Shared X by Column, Y by Row¶
In [5]:
val p1 = letsPlot(data) { x = mpg; y = wt } + geomPoint { color = origin } + ggtitle("Weight vs MPG")
val p2 = letsPlot(data) { x = hp; y = wt } + geomPoint { color = origin } + ggtitle("Weight vs HP")
val p3 = letsPlot(data) { x = mpg; y = accel } + geomPoint { color = origin } + ggtitle("Accel vs MPG")
val p4 = letsPlot(data) { x = hp; y = accel } + geomPoint { color = origin } + ggtitle("Accel vs HP")
gggrid(listOf(p1, p2, p3, p4), ncol = 2, guides = "collect",
sharex = "col",
sharey = "row"
) + ggsize(800, 600) + ggtb()
Out[5]:
Shared Both X and Y (all)¶
In [6]:
val p1 = letsPlot(df.filter { it[origin] == "US" }.toMap()) { x = mpg; y = hp } + geomPoint(color = "red") + ggtitle("US")
val p2 = letsPlot(df.filter { it[origin] == "Europe" }.toMap()) { x = mpg; y = hp } + geomPoint(color = "blue") + ggtitle("Europe")
val p3 = letsPlot(df.filter { it[origin] == "Asia" }.toMap()) { x = mpg; y = hp } + geomPoint(color = "green") + ggtitle("Asia")
gggrid(listOf(p1, p2, p3), ncol = 3,
sharex = "all",
sharey = "all"
) + ggsize(900, 350) + ggtb()
Out[6]: