Change the appearance of a log graph with two x axes

I would like to improve the overall look and feel of the two log graphs generated by the Python code below. The first graph represents the optimized methods while the second graph represents the unoptimized methods. On each graph, the black curves represent Method A which has x as the parameter, while the green curve represents Method B which has u as the parameter. All the curves have the log of execution time as the y-axis.

The graphs look messy at this point. I would like to make it look more professional and ready for publication. If there is a suggestion of how to better present the data, then that would be great.

Apart from beautifying the graphs, I welcome code optimization.

My dummy code with actual data is as follows:

import matplotlib.pyplot as plt
import numpy as np

x = range(10, 105, 5)
u = [10, 100, 250, 500, 1000, 2500, 5000, 7500, 10000]

data = {'Method A1': [0.2193, 0.2349, 0.2263, 0.2304, 0.2411, 0.2551, 0.246, 0.2363, 0.253, 0.2243, 0.233, 0.2417, 0.2563, 0.2592, 0.2563, 0.2505, 0.2445, 0.2488, 0.2486],
'Method A2': [1.6404, 1.8006, 1.6816, 1.7445, 1.6724, 1.8007, 1.7735, 1.9317, 1.8077, 1.8712, 1.8505, 1.9404, 1.9743, 1.9625, 2.0065, 2.0281, 2.07, 2.1143, 2.147],
'Method A3': [3.5524, 3.7176, 3.7293, 3.7512, 3.761, 3.8022, 3.8557, 3.9332, 4.0124, 4.0601, 4.1325, 4.2427, 4.3749, 4.6043, 4.5843, 4.5209, 4.5866, 4.6399, 4.7655],
'Method A4': [1.4258, 1.6331, 1.8261, 2.245, 2.3094, 2.7419, 3.1853, 3.5403, 4.2046, 4.935, 5.4563, 6.2366, 7.2951, 8.0295, 8.7971, 9.6959, 10.6778, 11.5294, 12.6728],
'Method A5': [5.0847, 5.9821, 7.3393, 9.3417, 12.025, 15.7723, 20.0009, 25.2742, 32.3163, 41.9064, 53.934, 70.2052, 91.6541, 116.1371, 137.8237, 174.3347, 201.1806, 247.8573, 298.069],
'Method A6': [5.3117, 5.9265, 7.3241, 9.3061, 11.9754, 15.4703, 20.0492, 25.3655, 33.0829, 41.6512, 54.6785, 71.442, 91.6323, 114.5206, 140.1839, 173.9388, 204.4305, 246.1606, 295.2418],
'Method A7': [5.5667, 11.9233, 23.7687, 42.4538, 72.1944, 164.1268, 414.3614, 494.0005, 694.1328, 1283.1182, 1319.9852, 1599.7988, 2436.2928, 2725.2453, 3559.4807, 4125.9421, 5123.7501, 5841.4343, 6680.9975],
'Method A8': [901.8982, 2852.6217, 7205.4927, 12797.464, 22445.0575, 34036.0515, 48509.2038, 63856.3554, 83411.4727, 106629.8965, 134948.5982, 168376.949, 205533.3217, 252012.0231, 302181.2505, 355911.3527, 424261.6199, 495973.9629, 568588.6134],
'Method A9': [528.8092, 2265.3305, 7519.4276, 13152.662, 23247.9131, 35632.529, 50289.4772, 65820.6071, 84575.7621, 107606.4105, 135534.6727, 170343.1367, 206705.3841, 253252.5434, 303249.0806, 359373.0741, 423570.4768, 496067.6073, 566162.0564],
'Method B':  [0.0747 , 0.7551  , 2.5258      , 7.2465    , 22.5389    , 116.0208   , 428.2362   , 947.8481    , 1673.4608   ]}

data_un = {'Method A1': [0.2401, 0.2511, 0.255, 0.2455, 0.2485, 0.2583, 0.2597, 0.2523, 0.2486, 0.2689, 0.254, 0.2738, 0.2715, 0.2848, 0.2756, 0.2791, 0.2788, 0.2749, 0.3122],
'Method A2': [1.6694, 1.6829, 1.6942, 1.7269, 1.7026, 1.725, 1.7605, 1.7857, 1.8241, 1.8539, 1.8813, 1.9402, 1.9981, 2.006, 2.0274, 2.0828, 2.1066, 2.1464, 2.1885],
'Method A3': [3.7293, 3.7456, 3.8227, 3.7937, 3.8013, 3.8551, 4.0009, 3.9837, 4.1706, 4.0813, 4.1918, 4.3254, 4.5106, 4.6145, 4.7019, 4.675, 4.8829, 4.9019, 4.9844],
'Method A4': [1.5354, 1.7512, 1.9222, 2.3564, 2.4783, 2.9123, 3.333, 3.819, 4.4982, 5.0897, 5.6664, 6.6945, 7.6074, 8.8665, 9.7312, 10.6143, 11.8072, 12.775, 13.9342],
'Method A5': [5.1749, 6.0099, 7.5464, 9.4824, 12.1673, 15.6409, 20.3647, 25.8226, 33.238, 42.2363, 54.8962, 71.4938, 92.581, 114.5907, 152.1842, 187.1784, 207.8406, 243.6383, 293.4553],
'Method A6': [5.3827, 6.0323, 7.4828, 9.5272, 12.6335, 15.6725, 20.2511, 25.7538, 32.7233, 42.1604, 54.2705, 71.6362, 90.9412, 115.3979, 140.9124, 176.5032, 202.3874, 245.7669, 295.2132],
'Method A7': [5.5667, 11.9233, 23.7687, 42.4538, 72.1944, 164.1268, 414.3614, 494.0005, 694.1328, 1283.1182, 1319.9852, 1599.7988, 2436.2928, 2725.2453, 3559.4807, 4125.9421, 5123.7501, 5841.4343, 6680.9975],
'Method A8': [901.8982, 2852.6217, 7205.4927, 12797.464, 22445.0575, 34036.0515, 48509.2038, 63856.3554, 83411.4727, 106629.8965, 134948.5982, 168376.949, 205533.3217, 252012.0231, 302181.2505, 355911.3527, 424261.6199, 495973.9629, 568588.6134],
'Method A9': [528.8092, 2265.3305, 7519.4276, 13152.662, 23247.9131, 35632.529, 50289.4772, 65820.6071, 84575.7621, 107606.4105, 135534.6727, 170343.1367, 206705.3841, 253252.5434, 303249.0806, 359373.0741, 423570.4768, 496067.6073, 566162.0564],
'Method B':  [44.0913, 517.6457, 1589.9273   , 3891.1677 , 13759.2301 , 72513.3247 , 267647.625 , 592405.0625 , 1045913.1142]}

for variant in ['Optimised', 'Unoptimised']:
if variant == 'Unoptimised':
data = data_un

fig, ax1 = plt.subplots()
ax2 = ax1.twiny()
prixcol = 'black'
sec_col = 'green'

linestyle_str = ['solid', 'solid', 'solid', 'dotted', 'dotted', 'dotted', 'dashed', 'dashed', 'dashed', 'dashdot']
marker_str = ['o', 'D', '^', 'o', 'D', '^', 'o', 'D', '^']

curves = {}
for i, method in enumerate(list(data.keys())):
if i < 9:
curves[i] = ax1.plot(x, np.log(data[method]), label = method, linestyle = linestyle_str[i], marker = marker_str[i], color = prixcol)
else:
curves[i] = ax2.plot(u, np.log(data[method]), label = method, linestyle = linestyle_str[i], color = sec_col)

ax1.tick_params(axis = 'y', colors = prixcol)
ax1.tick_params(axis = 'x', colors = prixcol)
ax2.tick_params(axis = 'x', colors = sec_col)

ax1.set_xticks(x)
ax2.set_xticks(u)

ax2.set_xticklabels(u, rotation=45, ha='right')

ax1.grid(color = prixcol, alpha = 0.5)
ax2.grid(color = sec_col, alpha = 0.5)

legend = ax1.legend([curves[i][0] for i in range(10)], [curves[i][0].get_label() for i in range(10)], loc = 'upper right')

ax1.set_xlabel("x", color = prixcol)
ax2.set_xlabel("u", color = sec_col)
ax1.set_ylabel("log[Execution time (sec)]", color = prixcol)
plt.show()


Graph 1

Graph 2

• Crucially - does the publication accept colour? Does the publication accept SVG? Sep 12, 2023 at 14:16
• In the algorithm being measured is there any mathematical relationship between x and u? If not I find it somewhat difficult to justify having these on the same graph. Sep 12, 2023 at 14:20
• stats.stackexchange.com is a better place for recommendations on how to present data. I don’t think that fits here. Getting rid of the grid and the heavy markers is the first thing to do to improve the graph. It’s just way too busy. I always recommend Edward Tufte’s book to learn about designing graphs. Sep 12, 2023 at 14:33

improve the overall look

import matplotlib.pyplot as plt


Matplotlib is wonderful, it can display anything. But by default it tends to be a little on the ugly side.

Consider starting with

import seaborn as sns


Also, storing observations in well-named dataframe columns will let seaborn offer some convenient legend defaults.

If you desire still bigger aesthetic changes, you might go with ggplot.