A Grammar of Graphics for Python providing a declarative approach to data visualization similar to R's ggplot2
—
Watermarks allow you to add image overlays to your plots for branding, attribution, or decorative purposes. The watermark functionality in plotnine provides flexible positioning and styling options to integrate images seamlessly with your visualizations.
Add image watermarks with customizable positioning, transparency, and styling.
def watermark(filename, xo=None, yo=None, alpha=0.5, **kwargs):
"""
Add image watermark to plot.
Overlays an image on the plot at specified coordinates with configurable
transparency and positioning options. Useful for adding logos, attribution
marks, or decorative elements.
Parameters:
- filename: str, path to watermark image file (supports PNG, JPG, etc.)
- xo: float, x-axis offset for watermark positioning (data coordinates)
- yo: float, y-axis offset for watermark positioning (data coordinates)
- alpha: float, transparency level (0=fully transparent, 1=fully opaque)
- **kwargs: additional matplotlib image parameters
- extent: tuple, (left, right, bottom, top) positioning in data coordinates
- aspect: str, aspect ratio handling ('auto', 'equal')
- interpolation: str, image interpolation method
- resample: bool, whether to resample image
- url: str, URL for clickable watermarks
- zorder: float, drawing order (higher values drawn on top)
Returns:
Watermark layer that can be added to ggplot objects
"""# Add logo watermark to bottom right
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('logo.png', xo=0.8, yo=0.1, alpha=0.7)
# Add watermark with custom transparency
ggplot(data, aes(x='date', y='value')) + \
geom_line() + \
watermark('company_logo.png', alpha=0.3)# Position watermark using data coordinates
max_x = data['x'].max()
max_y = data['y'].max()
ggplot(data, aes(x='x', y='y')) + \
geom_scatter() + \
watermark('watermark.png', xo=max_x * 0.8, yo=max_y * 0.9, alpha=0.5)
# Use extent for precise positioning
ggplot(data, aes(x='year', y='sales')) + \
geom_line() + \
watermark('brand.png', extent=(2015, 2018, 50, 100), alpha=0.4)# Add multiple watermarks for complex branding
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('logo.png', xo=0.05, yo=0.95, alpha=0.8) + \ # Top left
watermark('attribution.png', xo=0.95, yo=0.05, alpha=0.6) # Bottom right# Control drawing order and appearance
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('background.png', alpha=0.2, zorder=0) + \ # Behind points
watermark('foreground.png', alpha=0.8, zorder=10) # In front of points
# Custom interpolation for image quality
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('high_res_logo.png', alpha=0.7,
interpolation='bilinear', resample=True)# Corporate report watermark
ggplot(sales_data, aes(x='quarter', y='revenue')) + \
geom_col(fill='steelblue') + \
watermark('company_logo.png', xo=0.85, yo=0.9, alpha=0.6) + \
theme_minimal() + \
labs(title='Quarterly Revenue Report',
subtitle='Confidential - Internal Use Only')
# Academic publication watermark
ggplot(research_data, aes(x='treatment', y='response')) + \
geom_boxplot() + \
watermark('university_seal.png', xo=0.02, yo=0.02, alpha=0.3) + \
theme_classic() + \
labs(title='Treatment Effect Analysis')# Watermark that adapts to theme
ggplot(data, aes(x='x', y='y', color='group')) + \
geom_point() + \
facet_wrap('category') + \
watermark('logo.png', alpha=0.4) + \
theme_dark() # Watermark works with dark theme
# Conditional watermarks based on data
if data['confidential'].any():
plot += watermark('confidential.png', xo=0.5, yo=0.5, alpha=0.8)# Different image formats
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('logo.png', alpha=0.7) # PNG with transparency
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('photo.jpg', alpha=0.5) # JPEG format
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('vector.svg', alpha=0.6) # SVG format (if supported)# Position based on plot data range
x_range = data['x'].max() - data['x'].min()
y_range = data['y'].max() - data['y'].min()
ggplot(data, aes(x='x', y='y')) + \
geom_point() + \
watermark('logo.png',
xo=data['x'].min() + x_range * 0.1,
yo=data['y'].max() - y_range * 0.1,
alpha=0.6)# Handle missing watermark files gracefully
import os
watermark_file = 'logo.png'
plot = ggplot(data, aes(x='x', y='y')) + geom_point()
if os.path.exists(watermark_file):
plot += watermark(watermark_file, alpha=0.6)
else:
print(f"Watermark file {watermark_file} not found")
# Optimize watermark size for performance
# Use appropriately sized images to avoid memory issues with large plots# Company branding
ggplot(data, aes(x='metric', y='value')) + \
geom_col() + \
watermark('company_logo.png', xo=0.9, yo=0.1, alpha=0.5) + \
theme_minimal()# Confidential data marking
ggplot(sensitive_data, aes(x='x', y='y')) + \
geom_point() + \
watermark('confidential_stamp.png', xo=0.5, yo=0.5, alpha=0.7)# Subtle background decoration
ggplot(data, aes(x='x', y='y')) + \
watermark('subtle_pattern.png', alpha=0.1, zorder=0) + \
geom_point() + \
theme_void()Install with Tessl CLI
npx tessl i tessl/pypi-plotnine