This page demonstrates how to use CodeBlock elements in JSPlots to display code with syntax highlighting and execute Julia code to generate visualizations.
CodeBlocks are perfect for creating literate programming documents where you show both the code and its output.
Supported languages: Julia (executable), Python, R, C++, C, Java, JavaScript, SQL, PostgreSQL (PL/pgSQL), Rust, and more (display only).
Here we create a CodeBlock from a function that generates random stock data. The code is displayed with syntax highlighting, and we can execute it to get the data.
function generate_sample_data()
n = 50
x = 1:n
y1 = cumsum(randn(rng, n)) .+ 100
y2 = cumsum(randn(rng, n)) .+ 100
return DataFrame(
day = x,
stock_a = y1,
stock_b = y2,
category = repeat(["Tech", "Finance"], inner=25)
)
end
Data generated by the code above
Data: df1
This example shows how to display the code that creates a chart, alongside the chart itself.
function create_pie_chart()
df = DataFrame(
category = ["Product A", "Product B", "Product C", "Product D"],
sales = [45000, 32000, 28000, 15000]
)
return PieChart(:sales_pie, df, :pie_data;
color_cols = [:category],
value_cols = [:sales],
title = "Sales by Product"
), df
end
Data: pie_data
Sometimes you want to show code for educational purposes without executing it. Here's an example:
# Tutorial: Creating a Simple Scatter Plot
using JSPlots, DataFrames, StableRNGs
rng = StableRNG(42)
# Step 1: Create your data
df = DataFrame(
x = rand(rng, 100),
y = rand(rng, 100),
size = rand(rng, 100) .* 50,
color = rand(rng, ["red", "blue", "green"], 100)
)
# Step 2: Create the scatter plot
scatter = ScatterPlot(:my_scatter, df, :my_data;
x_cols = [:x],
y_cols = [:y],
size_col = :size,
color_cols = [:color],
title = "My First Scatter Plot"
)
# Step 3: Export to HTML
create_html(scatter, "output.html")
This example demonstrates how to show multiple code blocks that build on each other, creating a complete data analysis workflow.
function prepare_analysis_data()
dates = Date(2024,1,1):Day(1):Date(2024,1,31)
df = DataFrame(
date = dates,
temperature = 15 .+ 10 .* sin.(2π .* (1:31) ./ 31) .+ randn(rng, 31) .* 2,
humidity = 60 .+ 15 .* cos.(2π .* (1:31) ./ 31) .+ randn(rng, 31) .* 5,
city = repeat(["New York", "Boston"], inner=16)[1:31]
)
return df
end
# Create a line chart showing temperature trends
weather_chart = LineChart(:weather, weather_df, :weather_data;
x_cols = [:date],
y_cols = [:temperature, :humidity],
title = "January Weather Patterns",
notes = "Temperature (°C) and Humidity (%)"
)
Data: weather_data
CodeBlock supports displaying code in multiple programming languages with proper syntax highlighting.
Note: Only Julia code can be executed. Code in other languages is for display purposes only.
Python code is displayed with proper syntax highlighting.
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
# Example usage
numbers = [64, 34, 25, 12, 22, 11, 90]
sorted_numbers = merge_sort(numbers)
print(f"Sorted array: {sorted_numbers}")
R statistical code with proper syntax highlighting.
# Multiple linear regression in R
# Load the mtcars dataset
data(mtcars)
# Fit a linear model
model <- lm(mpg ~ cyl + hp + wt, data = mtcars)
# Display the summary
summary(model)
# Create a plot
plot(model$fitted.values, model$residuals,
main = "Residual Plot",
xlab = "Fitted Values",
ylab = "Residuals")
abline(h = 0, col = "red", lty = 2)
# Calculate predictions
new_data <- data.frame(cyl = c(4, 6, 8), hp = c(110, 150, 200), wt = c(2.5, 3.0, 3.5))
predictions <- predict(model, newdata = new_data)
print(predictions)
SQL queries with proper syntax highlighting.
-- Complex customer analytics query
WITH customer_metrics AS (
SELECT
c.customer_id,
c.name,
COUNT(DISTINCT o.order_id) as total_orders,
SUM(o.total_amount) as lifetime_value,
AVG(o.total_amount) as avg_order_value,
MAX(o.order_date) as last_order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_date >= DATE_SUB(CURRENT_DATE, INTERVAL 1 YEAR)
GROUP BY c.customer_id, c.name
),
customer_segments AS (
SELECT
*,
CASE
WHEN lifetime_value > 10000 THEN 'VIP'
WHEN lifetime_value > 5000 THEN 'Premium'
WHEN lifetime_value > 1000 THEN 'Standard'
ELSE 'Basic'
END as segment
FROM customer_metrics
)
SELECT
segment,
COUNT(*) as customer_count,
AVG(total_orders) as avg_orders_per_customer,
SUM(lifetime_value) as segment_revenue
FROM customer_segments
GROUP BY segment
ORDER BY segment_revenue DESC;
C++ code with proper syntax highlighting.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
// Template class for a simple generic stack
template<typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(const T& element) {
elements.push_back(element);
}
T pop() {
if (elements.empty()) {
throw std::out_of_range("Stack is empty");
}
T top = elements.back();
elements.pop_back();
return top;
}
bool empty() const {
return elements.empty();
}
size_t size() const {
return elements.size();
}
};
int main() {
// Example usage
Stack<int> numbers;
// Push numbers
for (int i = 1; i <= 5; ++i) {
numbers.push(i * 10);
}
// Pop and print
while (!numbers.empty()) {
std::cout << numbers.pop() << " ";
}
std::cout << std::endl;
return 0;
}
Modern JavaScript (ES6+) code with proper syntax highlighting.
// Asynchronous data fetching and processing
class DataProcessor {
constructor(apiUrl) {
this.apiUrl = apiUrl;
this.cache = new Map();
}
// Fetch data with caching
async fetchData(endpoint) {
const cacheKey = `${this.apiUrl}/${endpoint}`;
if (this.cache.has(cacheKey)) {
console.log('Returning cached data');
return this.cache.get(cacheKey);
}
try {
const response = await fetch(cacheKey);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
this.cache.set(cacheKey, data);
return data;
} catch (error) {
console.error('Failed to fetch data:', error);
throw error;
}
}
// Process data with array methods
processUsers(users) {
return users
.filter(user => user.active)
.map(user => ({
id: user.id,
name: user.name,
email: user.email,
joinDate: new Date(user.created_at)
}))
.sort((a, b) => b.joinDate - a.joinDate)
.slice(0, 10);
}
}
// Usage example
const processor = new DataProcessor('https://api.example.com');
async function displayTopUsers() {
try {
const users = await processor.fetchData('users');
const topUsers = processor.processUsers(users);
topUsers.forEach(user => {
console.log(`${user.name} - ${user.email}`);
});
} catch (error) {
console.error('Error displaying users:', error);
}
}
displayTopUsers();
Rust provides memory safety without garbage collection through its ownership system.
#[derive(Debug)]
enum ParseError {
InvalidFormat,
OutOfRange,
}
struct DataPoint {
timestamp: i64,
value: f64,
}
impl DataPoint {
fn new(timestamp: i64, value: f64) -> Result<Self, ParseError> {
if value < 0.0 || value > 100.0 {
return Err(ParseError::OutOfRange);
}
Ok(DataPoint { timestamp, value })
}
}
fn parse_data(input: &str) -> Result<Vec<DataPoint>, ParseError> {
input
.lines()
.filter(|line| !line.trim().is_empty())
.map(|line| {
let parts: Vec<&str> = line.split(',').collect();
if parts.len() != 2 {
return Err(ParseError::InvalidFormat);
}
let timestamp = parts[0]
.trim()
.parse::<i64>()
.map_err(|_| ParseError::InvalidFormat)?;
let value = parts[1]
.trim()
.parse::<f64>()
.map_err(|_| ParseError::InvalidFormat)?;
DataPoint::new(timestamp, value)
})
.collect()
}
fn calculate_statistics(data: &[DataPoint]) -> (f64, f64) {
let sum: f64 = data.iter().map(|dp| dp.value).sum();
let mean = sum / data.len() as f64;
let variance: f64 = data
.iter()
.map(|dp| (dp.value - mean).powi(2))
.sum::<f64>() / data.len() as f64;
(mean, variance.sqrt())
}
fn main() {
let input = "1609459200,45.5\n1609545600,52.3\n1609632000,48.9";
match parse_data(input) {
Ok(data) => {
let (mean, std_dev) = calculate_statistics(&data);
println!("Mean: {:.2}, Std Dev: {:.2}", mean, std_dev);
}
Err(e) => eprintln!("Error parsing data: {:?}", e),
}
}
The same algorithm implemented in different languages:
function binary_search(arr::Vector, target)
left, right = 1, length(arr)
while left <= right
mid = div(left + right, 2)
if arr[mid] == target
return mid
elseif arr[mid] < target
left = mid + 1
else
right = mid - 1
end
end
return nothing # Not found
end
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return None # Not found
int binary_search(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // Not found
}
| Method | Syntax | Executable? |
|---|---|---|
| From Function | CodeBlock(my_function) |
✓ Yes |
| From File | CodeBlock("script.jl") |
✓ Yes |
| From String | CodeBlock(code_str, Val(:code)) |
✗ No |
For executable CodeBlocks, call them like functions using codeblock():
# Single return value
data = code_block()
# Multiple return values
chart, data = code_block()
# Alternative (but cb() is preferred)
data = execute_codeblock(code_block)
notes parameter to provide context about what the code doesCodeTracking.jl for better resultsThis page demonstrated CodeBlock features:
Key Points:
CodeBlocks make your analyses reproducible and educational by showing the code that generated every visualization!
This page was created using JSPlots.jl.