Update tech_docs/webdev/hugo.md
This commit is contained in:
@@ -1,3 +1,122 @@
|
|||||||
|
For **statistics and data science visuals** in hobby projects (e.g., distributions, regression plots, time series, clustering), here’s the optimal workflow balancing **quality, performance, and ease of use**:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1. Recommended Tools by Task**
|
||||||
|
#### **A. Static Visuals (PNG/SVG)**
|
||||||
|
| Task | Best Tool (Python) | Best Tool (R) | Output Format |
|
||||||
|
|-----------------------|--------------------------|------------------------|---------------|
|
||||||
|
| Distributions | Seaborn (`histplot`, `kdeplot`) | ggplot2 (`geom_histogram`, `geom_density`) | PNG (if dense data) / SVG (if simple) |
|
||||||
|
| Scatter/Regression | Seaborn (`regplot`, `lmplot`) | ggplot2 (`geom_smooth`, `geom_point`) | SVG (for interactivity later) |
|
||||||
|
| Time Series | Matplotlib (`plot_date`) + Seaborn | ggplot2 (`geom_line`) | PNG (long series) |
|
||||||
|
| Heatmaps/Correlation | Seaborn (`heatmap`) | ggplot2 (`geom_tile`) | PNG (large matrices) |
|
||||||
|
| Box/Violin Plots | Seaborn (`boxplot`, `violinplot`) | ggplot2 (`geom_boxplot`) | SVG |
|
||||||
|
|
||||||
|
#### **B. Interactive Visuals (Embeddable in Hugo)**
|
||||||
|
| Task | Best Tool | Output Format |
|
||||||
|
|-----------------------|--------------------------|------------------------|
|
||||||
|
| Exploratory hover plots | Plotly Express (Python/R) | HTML (embed as `<iframe>`) |
|
||||||
|
| Linked brushing | Altair (Python) + Vega | JSON (via Hugo shortcode) |
|
||||||
|
| Animated transitions | Plotly (`animation_frame`) | GIF/MP4 (FFmpeg-optimized) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2. File Format Guidelines**
|
||||||
|
- **Use PNG if:**
|
||||||
|
- Plot has >1,000 data points (e.g., large scatterplots).
|
||||||
|
- You’re using transparency (`plt.savefig(..., transparent=True)`).
|
||||||
|
- Example:
|
||||||
|
```python
|
||||||
|
# Python (Seaborn)
|
||||||
|
sns.scatterplot(data=df, x="x", y="y").get_figure().savefig("plot.png", dpi=200, bbox_inches="tight")
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Use SVG if:**
|
||||||
|
- Plot is simple (e.g., boxplots, small line charts).
|
||||||
|
- You want to edit colors/text later in Inkscape.
|
||||||
|
- Example:
|
||||||
|
```r
|
||||||
|
# R (ggplot2)
|
||||||
|
ggsave("plot.svg", plot, device = svg, width=8, height=6)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3. Optimization Pipeline**
|
||||||
|
#### **For PNGs:**
|
||||||
|
1. Generate high-res (300dpi) PNGs directly from Python/R.
|
||||||
|
2. Compress with `oxipng` (lossless):
|
||||||
|
```bash
|
||||||
|
oxipng -o 4 --strip safe plot.png
|
||||||
|
```
|
||||||
|
- (Alternative: Use ImageMagick `-quality 90 -strip`).
|
||||||
|
|
||||||
|
#### **For SVGs:**
|
||||||
|
1. Export from tool (avoid unnecessary metadata).
|
||||||
|
2. Crush with `svgo`:
|
||||||
|
```bash
|
||||||
|
npx svgo plot.svg --config='
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"removeXMLProcInst",
|
||||||
|
"removeComments",
|
||||||
|
"removeDoctype"
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **4. Hugo Integration**
|
||||||
|
- **Static images**: Place in `/static/images/` and reference in Markdown:
|
||||||
|
```md
|
||||||
|

|
||||||
|
```
|
||||||
|
- **Interactive plots**: Use Hugo shortcodes for iframes:
|
||||||
|
```html
|
||||||
|
{{< iframe src="/plots/interactive_plot.html" width="100%" height="500px" >}}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5. Example Workflows**
|
||||||
|
#### **Python (Seaborn + Plotly)**
|
||||||
|
```python
|
||||||
|
# Static plot
|
||||||
|
sns.histplot(data=df, x="value").get_figure().savefig("histogram.png", dpi=300)
|
||||||
|
|
||||||
|
# Interactive plot
|
||||||
|
fig = px.scatter(df, x="x", y="y", hover_data=["label"])
|
||||||
|
fig.write_html("scatter.html") # Embed in Hugo
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **R (ggplot2 + Plotly)**
|
||||||
|
```r
|
||||||
|
# Static plot
|
||||||
|
ggsave("boxplot.svg", ggplot(df, aes(x=group, y=value)) + geom_boxplot())
|
||||||
|
|
||||||
|
# Interactive plot
|
||||||
|
ggplotly(p) %>% htmlwidgets::saveWidget("boxplot.html")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **6. Tools to Avoid**
|
||||||
|
- **D3.js**: Overkill unless you need custom interactivity.
|
||||||
|
- **Bokeh**: Heavy for static sites; Plotly is simpler.
|
||||||
|
- **RAWGraphs**: Better for one-offs, not automation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **Final Recommendation**
|
||||||
|
- **Default to Seaborn (Python) / ggplot2 (R)** → Export as **PNG** for dense plots, **SVG** for simple ones.
|
||||||
|
- **Add interactivity sparingly** with Plotly (saved as HTML).
|
||||||
|
- **Optimize all files** (`oxipng`/`svgo`) before Hugo deployment.
|
||||||
|
|
||||||
|
For hobby projects, this balances **speed, quality, and fun**! Want a sample Hugo project structure with automation scripts?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
To get started with your data visualization project using Hugo, Bootstrap, and Chart.js, follow these steps:
|
To get started with your data visualization project using Hugo, Bootstrap, and Chart.js, follow these steps:
|
||||||
|
|
||||||
1. Project Setup:
|
1. Project Setup:
|
||||||
|
|||||||
Reference in New Issue
Block a user