-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgallery_scatter_bubble_chart.cpp
More file actions
177 lines (158 loc) 路 6.22 KB
/
Copy pathgallery_scatter_bubble_chart.cpp
File metadata and controls
177 lines (158 loc) 路 6.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/**
* @file gallery_scatter_bubble_chart.cpp
* @brief World Development Indicators Multi-Dimensional Bubble Chart
* @author plotly.cpp contributors
* @date 2025
*
* @example gallery_scatter_bubble_chart.cpp
* This gallery example demonstrates creating a sophisticated bubble chart using
* Plotly.cpp to visualize world development indicators across multiple
* dimensions. It combines scatter plot positioning with bubble size and color
* to represent four different metrics simultaneously.
*
* Features demonstrated:
* - Multi-dimensional data visualization (GDP, Life Expectancy, Population,
* Happiness)
* - Bubble size mapping to represent population data
* - Color scale mapping to represent happiness scores
* - Regional grouping with separate traces for easy filtering
* - Logarithmic scale for GDP data to handle wide value ranges
* - Interactive hover templates with detailed country information
* - Viridis color scale with custom colorbar configuration
* - Synthetic data generation with realistic correlations
*
* Data dimensions visualized:
* - X-axis: GDP per Capita (logarithmic scale)
* - Y-axis: Life Expectancy in years
* - Bubble size: Population in millions
* - Bubble color: Happiness Score (0-10 scale)
* - Regional grouping: North America, Asia, Europe, South America, Oceania
*
* The visualization enables exploration of complex relationships between
* economic, social, and demographic indicators across different world regions.
*
* @image html scatter_bubble_chart.png "World Development Indicators Bubble
* Chart"
*
*/
#include "plotly/plotly.hpp"
#include "utils/arg_parser.hpp"
#include <algorithm>
#include <cstddef>
#include <random>
#include <string>
#include <vector>
auto main(int argc, char *argv[]) -> int {
// Parse command line arguments
auto args = parseGalleryArgs(argc, argv);
plotly::Figure fig;
fig.openBrowser(args.headless);
// Generate synthetic multi-dimensional data representing countries
std::vector<std::string> countries = {
"USA", "China", "Japan", "Germany", "India",
"UK", "France", "Italy", "Brazil", "Canada",
"Russia", "South Korea", "Australia", "Spain", "Mexico",
"Indonesia", "Netherlands", "Saudi Arabia", "Turkey", "Taiwan"};
const size_t n = countries.size();
std::vector<double> gdpPerCapita, lifeExpectancy, population, happiness;
std::vector<std::string> regions;
// Random generators
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> gdpDist(20000, 80000);
std::uniform_real_distribution<double> lifeDist(70, 85);
std::uniform_real_distribution<double> popDist(10, 1400);
std::uniform_real_distribution<double> happinessDist(4.5, 8.0);
std::vector<std::string> regionList = {"North America", "Asia", "Europe",
"South America", "Oceania"};
// Generate data with some correlation patterns
for (size_t i = 0; i < n; i++) {
double gdp = gdpDist(gen);
double life =
65 + (gdp - 20000) / 2000 + std::normal_distribution<double>(0, 3)(gen);
double pop = popDist(gen);
double happy =
3 + life / 15 + std::normal_distribution<double>(0, 0.8)(gen);
// Clamp values to reasonable ranges
life = std::max(65.0, std::min(85.0, life));
happy = std::max(3.0, std::min(8.5, happy));
gdpPerCapita.push_back(gdp);
lifeExpectancy.push_back(life);
population.push_back(pop);
happiness.push_back(happy);
regions.push_back(regionList[i % regionList.size()]);
}
// Create separate traces for each region
std::vector<plotly::Object> traces;
std::vector<std::string> colors = {"red", "blue", "green", "orange",
"purple"};
for (size_t r = 0; r < regionList.size(); r++) {
std::vector<double> regionGDP, regionLife, regionPop, regionHappy;
std::vector<std::string> regionCountries;
// Filter data by region
for (size_t i = 0; i < n; i++) {
if (regions[i] == regionList[r]) {
regionGDP.push_back(gdpPerCapita[i]);
regionLife.push_back(lifeExpectancy[i]);
regionPop.push_back(population[i]);
regionHappy.push_back(happiness[i]);
regionCountries.push_back(countries[i]);
}
}
if (!regionGDP.empty()) {
plotly::Object trace = {
{"type", "scatter"},
{"mode", "markers"},
{"x", regionGDP},
{"y", regionLife},
{"text", regionCountries},
{"name", regionList[r]},
{"marker",
{{"size", regionPop},
{"sizemode", "diameter"},
{"sizeref", 3.0},
{"sizemin", 4},
{"color", regionHappy},
{"colorscale", "Viridis"},
{"showscale", r == 0}, // Show colorbar only for first trace
{"colorbar",
{{"title", "Happiness Score"}, {"titleside", "right"}}},
{"line", {{"color", colors[r]}, {"width", 2}}}}},
{"hovertemplate",
"%{text}<br>GDP per Capita: $%{x:,.0f}<br>" +
std::string("Life Expectancy: %{y:.1f} years<br>") +
"Population: %{marker.size:.0f}M<br>" +
"Happiness: %{marker.color:.1f}<extra></extra>"}};
traces.push_back(trace);
}
}
// Create layout
plotly::Object layout = {
{"title",
{{"text", "World Development Indicators<br>" +
std::string("<sub>Bubble size = Population (millions), ") +
"Color = Happiness Score</sub>"},
{"font", {{"size", 16}}}}},
{"xaxis",
{{"title", "GDP per Capita (USD)"},
{"type", "log"},
{"showgrid", true}}},
{"yaxis", {{"title", "Life Expectancy (years)"}, {"showgrid", true}}},
{"width", 1000},
{"height", 700},
{"showlegend", true},
{"hovermode", "closest"}};
// Create the plot
fig.newPlot(traces, layout);
if (!args.headless) {
fig.waitClose();
} else {
// Save image instead of opening browser
plotly::Object imageOpts = {{"format", "png"},
{"width", 1000},
{"height", 700},
{"filename", "scatter_bubble_chart"}};
fig.downloadImage(imageOpts);
}
return 0;
}