Skip to content

Commit c69fdb0

Browse files
feat(letsplot): implement scatter-marginal (#6131)
## Implementation: `scatter-marginal` - python/letsplot Implements the **python/letsplot** version of `scatter-marginal`. **File:** `plots/scatter-marginal/implementations/python/letsplot.py` **Parent Issue:** #2005 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25592948372)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent b98610b commit c69fdb0

2 files changed

Lines changed: 208 additions & 164 deletions

File tree

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
scatter-marginal: Scatter Plot with Marginal Distributions
3-
Library: letsplot 4.8.2 | Python 3.13.11
4-
Quality: 90/100 | Created: 2025-12-26
3+
Library: letsplot 4.9.0 | Python 3.13.13
4+
Quality: 95/100 | Updated: 2026-05-09
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
911
from lets_plot import * # noqa: F403
@@ -12,6 +14,16 @@
1214

1315
LetsPlot.setup_html() # noqa: F405
1416

17+
# Theme tokens
18+
THEME = os.getenv("ANYPLOT_THEME", "light")
19+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
20+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
21+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
22+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
23+
24+
BRAND = "#009E73" # Okabe-Ito position 1
25+
ACCENT = "#D55E00" # Okabe-Ito position 2
26+
1527
# Data - bivariate data with correlation
1628
np.random.seed(42)
1729
n = 200
@@ -24,20 +36,24 @@
2436
x_min, x_max = df["x"].min() - 0.5, df["x"].max() + 0.5
2537
y_min, y_max = df["y"].min() - 0.5, df["y"].max() + 0.5
2638

27-
# Main scatter plot with integrated title
39+
# Main scatter plot
2840
main_scatter = (
2941
ggplot(df, aes(x="x", y="y")) # noqa: F405
30-
+ geom_point(color="#306998", size=4, alpha=0.65) # noqa: F405
42+
+ geom_point(color=BRAND, size=4, alpha=0.65) # noqa: F405
3143
+ labs( # noqa: F405
32-
x="X Value", y="Y Value", title="scatter-marginal · letsplot · pyplots.ai"
44+
x="Measurement A", y="Measurement B", title="scatter-marginal · letsplot · anyplot.ai"
3345
)
3446
+ scale_x_continuous(limits=[x_min, x_max]) # noqa: F405
3547
+ scale_y_continuous(limits=[y_min, y_max]) # noqa: F405
3648
+ theme_minimal() # noqa: F405
3749
+ theme( # noqa: F405
38-
plot_title=element_text(size=24), # noqa: F405
39-
axis_title=element_text(size=20), # noqa: F405
40-
axis_text=element_text(size=16), # noqa: F405
50+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), # noqa: F405
51+
panel_background=element_rect(fill=PAGE_BG), # noqa: F405
52+
panel_grid_major=element_line(color=INK_SOFT, size=0.2), # noqa: F405
53+
plot_title=element_text(size=24, color=INK), # noqa: F405
54+
axis_title=element_text(size=20, color=INK), # noqa: F405
55+
axis_text=element_text(size=16, color=INK_SOFT), # noqa: F405
56+
axis_line=element_line(color=INK_SOFT), # noqa: F405
4157
)
4258
)
4359

@@ -46,19 +62,23 @@
4662
ggplot(df, aes(x="x")) # noqa: F405
4763
+ geom_histogram( # noqa: F405
4864
aes(y="..density.."), # noqa: F405
49-
fill="#306998",
50-
color="white",
51-
alpha=0.6,
65+
fill=BRAND,
66+
color=PAGE_BG,
67+
alpha=0.5,
5268
bins=25,
5369
)
54-
+ geom_density(color="#DC2626", size=1.5, alpha=0.8) # noqa: F405
70+
+ geom_density(color=ACCENT, size=1.5, alpha=0.8) # noqa: F405
5571
+ scale_x_continuous(limits=[x_min, x_max]) # noqa: F405
5672
+ theme_minimal() # noqa: F405
5773
+ theme( # noqa: F405
74+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), # noqa: F405
75+
panel_background=element_rect(fill=PAGE_BG), # noqa: F405
76+
panel_grid_major=element_line(color=INK_SOFT, size=0.15), # noqa: F405
5877
axis_title=element_blank(), # noqa: F405
5978
axis_text_x=element_blank(), # noqa: F405
6079
axis_ticks_x=element_blank(), # noqa: F405
61-
axis_text_y=element_text(size=16), # noqa: F405
80+
axis_text_y=element_text(size=14, color=INK_SOFT), # noqa: F405
81+
axis_line_x=element_blank(), # noqa: F405
6282
)
6383
)
6484

@@ -67,40 +87,42 @@
6787
ggplot(df, aes(x="y")) # noqa: F405
6888
+ geom_histogram( # noqa: F405
6989
aes(y="..density.."), # noqa: F405
70-
fill="#306998",
71-
color="white",
72-
alpha=0.6,
90+
fill=BRAND,
91+
color=PAGE_BG,
92+
alpha=0.5,
7393
bins=25,
7494
)
75-
+ geom_density(color="#DC2626", size=1.5, alpha=0.8) # noqa: F405
95+
+ geom_density(color=ACCENT, size=1.5, alpha=0.8) # noqa: F405
7696
+ coord_flip() # noqa: F405
7797
+ scale_x_continuous(limits=[y_min, y_max]) # noqa: F405
7898
+ theme_minimal() # noqa: F405
7999
+ theme( # noqa: F405
100+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), # noqa: F405
101+
panel_background=element_rect(fill=PAGE_BG), # noqa: F405
102+
panel_grid_major=element_line(color=INK_SOFT, size=0.15), # noqa: F405
80103
axis_title=element_blank(), # noqa: F405
81104
axis_text_y=element_blank(), # noqa: F405
82105
axis_ticks_y=element_blank(), # noqa: F405
83-
axis_text_x=element_text(size=16), # noqa: F405
84-
plot_margin=[0, 15, 0, 0], # noqa: F405
106+
axis_text_x=element_text(size=14, color=INK_SOFT), # noqa: F405
107+
axis_line_y=element_blank(), # noqa: F405
85108
)
86109
)
87110

88111
# Combine using ggbunch
89-
# Regions: (x, y, width, height) - relative coordinates
90112
combined = (
91113
ggbunch( # noqa: F405
92114
[top_hist, main_scatter, right_hist],
93115
[
94-
(0, 0.08, 0.76, 0.20), # Top histogram (below title space)
95-
(0, 0.28, 0.76, 0.72), # Main scatter plot (with title at top)
96-
(0.76, 0.28, 0.24, 0.72), # Right histogram (wider for tick labels)
116+
(0, 0.0, 0.76, 0.18), # Top histogram
117+
(0, 0.18, 0.76, 0.82), # Main scatter plot
118+
(0.76, 0.18, 0.24, 0.82), # Right histogram (aligned to bottom of main plot)
97119
],
98120
)
99121
+ ggsize(1600, 900) # noqa: F405
100122
)
101123

102124
# Save as PNG (scale 3x to get 4800 x 2700 px)
103-
export_ggsave(combined, filename="plot.png", path=".", scale=3)
125+
export_ggsave(combined, filename=f"plot-{THEME}.png", path=".", scale=3)
104126

105127
# Save HTML for interactive version
106-
export_ggsave(combined, filename="plot.html", path=".")
128+
export_ggsave(combined, filename=f"plot-{THEME}.html", path=".")

0 commit comments

Comments
 (0)