diff --git a/README.md b/README.md index 0f8479f1..278a87dc 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,31 @@ int main() ![Basic example](./examples/basic.png) +String x-axis labels with legend: +```cpp +#include "../matplotlibcpp.h" +#include +#include + +namespace plt = matplotlibcpp; + +int main() +{ + std::vector x = {"Jan 2021", "Feb 2021", "Mar 2021"}; + std::vector y = {58.4, 61.2, 63.9}; + + plt::named_plot("Vehicle speed (max)", x, y, "o-"); + plt::legend(); + plt::save("./string_xaxis_named_plot.png"); +} +``` + g++ examples/string_xaxis_named_plot.cpp -std=c++11 -I. -I/usr/include/python2.7 -lpython2.7 + +Expected behavior and constraints: +- `x` is a `std::vector` and `y` is numeric with matching length. +- String labels are mapped as categorical x values by matplotlib. +- Use `plt::save(...)` for headless runs or `plt::show()` for interactive runs. + Alternatively, matplotlib-cpp also supports some C++11-powered syntactic sugar: ```cpp #include diff --git a/examples/string_xaxis_named_plot.cpp b/examples/string_xaxis_named_plot.cpp new file mode 100644 index 00000000..6a1d80b0 --- /dev/null +++ b/examples/string_xaxis_named_plot.cpp @@ -0,0 +1,25 @@ +#include "../matplotlibcpp.h" +#include +#include + +namespace plt = matplotlibcpp; + +int main() +{ + const std::vector months = { + "Jan 2021", "Feb 2021", "Mar 2021", "Apr 2021", "May 2021" + }; + const std::vector speed_kmh = {58.4, 61.2, 63.9, 62.1, 65.0}; + + plt::figure_size(900, 500); + plt::named_plot("Vehicle speed (max)", months, speed_kmh, "o-"); + plt::title("Monthly peak speed"); + plt::xlabel("Month"); + plt::ylabel("Speed (km/h)"); + plt::legend(); + plt::tight_layout(); + + // Use save() for CI/headless usage; replace with show() for interactive runs. + plt::save("./string_xaxis_named_plot.png"); + return 0; +} diff --git a/matplotlibcpp.h b/matplotlibcpp.h index d95d46ad..c32765ce 100644 --- a/matplotlibcpp.h +++ b/matplotlibcpp.h @@ -1726,6 +1726,36 @@ bool named_plot(const std::string& name, const std::vector& x, const s return res; } +template +bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +{ + detail::_interpreter::get(); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = detail::get_array(x); + PyObject* yarray = detail::get_array(y); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(3); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, pystring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if (res) Py_DECREF(res); + + return res; +} + +template +bool named_semilogx(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") + template bool named_semilogx(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") {