简体   繁体   中英

How can I shift overlapping data points slightly along the x-axis in matplotlib?

I collected some data points for 4 different experimental setups, which are labeled "1", "2", "4" and "8". For each experimental setup, I collected 10 data points.

I am able to successfully plot these data points and draw an additional curve to show the average values for each setup.

However, I changed other settings in my experiments, and I can plot another figure like that. Now I hope to put everything in one single plot (2 sets of data points and two average curves), but everything look too crowded. My script for plotting and the plot are like these:

from numpy import *
import math
import matplotlib.pyplot as plt
import numpy as np

raw_1 = [0.38, 0.49, 0.25, 0.3, 0.4, 0.19, 0.45, 0.93, 0.44, 0.65] 
raw_2 = [0.27, 0.39, 0.09, 0.75, 0.79, 0.77, 0.31, 0.05, 0.73, 0.7]
raw_4 = [0.2, 0.84, 0.83, 0.7, 0.86, 0.2, 0.37, 0.41, 0.72, 0.29]
raw_8 = [0.2, 0.71, 0.31, 0.63, 0.24, 0.07, 0.2, 0.89, 0.34, 0.92]
y = np.array([raw_1, raw_2, raw_4, raw_8])
y = np.transpose(y)
y_mean = [mean(raw_1), mean(raw_2), mean(raw_4), mean(raw_8)]
x = [1,2,4,8]
xx = range(len(x))
plt.plot(xx, y[0], 'rx') 
plt.plot(xx, y[1], 'rx') 
plt.plot(xx, y[2], 'rx') 
plt.plot(xx, y[3], 'rx') 
plt.plot(xx, y[4], 'rx') 
plt.plot(xx, y[5], 'rx') 
plt.plot(xx, y[6], 'rx') 
plt.plot(xx, y[7], 'rx') 
plt.plot(xx, y[8], 'rx') 
plt.plot(xx, y[9], 'rx')

plt.xticks(xx,x)
leg = plt.legend(loc='upper left');

new_raw_1 = [0.217, 0.206, 0.222, 0.271, 0.212, 0.58, 0.333, 0.463, 0.314, 0.59] 
new_raw_2 = [0.511, 0.537, 0.565, 0.597, 0.527, 0.571, 0.505, 0.541, 0.542, 0.517]
new_raw_4 = [0.662, 0.552, 0.772, 0.436, 0.505, 0.577, 0.313, 0.796, 0.582, 0.574]
new_raw_8 = [0.511, 0.587, 0.591, 0.531, 0.522, 0.549, 0.593, 0.544, 0.552, 0.555]
y = np.array([new_raw_1, new_raw_2, new_raw_4, new_raw_8])
y = np.transpose(y)
y_mean_new = [mean(new_raw_1), mean(new_raw_2), mean(new_raw_4), mean(new_raw_8)]
x = [1,2,4,8]
xx = range(len(x))
plt.plot(xx, y[0], 'bo') 
plt.plot(xx, y[1], 'bo') 
plt.plot(xx, y[2], 'bo') 
plt.plot(xx, y[3], 'bo') 
plt.plot(xx, y[4], 'bo') 
plt.plot(xx, y[5], 'bo') 
plt.plot(xx, y[6], 'bo') 
plt.plot(xx, y[7], 'bo') 
plt.plot(xx, y[8], 'bo') 
plt.plot(xx, y[9], 'bo')
plt.plot(xx, y_mean_new, color='C0', marker='D', markersize=10, markerfacecolor='white', label='Avg A')
plt.plot(xx, y_mean, color='C1', marker='H', markersize=10, markerfacecolor='white', label='Avg B')
#plt.xticks(xx,x)
leg = plt.legend();


plt.show()

在此处输入图片说明

Currently, the blue circles and the red X markers are blocking each other. How should I modify my script to introduce a small x-axis shift between blue circles and red X markers, while still keeping xticks as "1", "2", "4", "8" with equal distances?

You can add an offset to the x positions simply by defining a different list of x coordinates for each series. This doesn't affect your ticks as you simply keep the original x positions for them. Here's an example:

from numpy import *
import math
import matplotlib.pyplot as plt
import numpy as np

raw_1 = [0.38, 0.49, 0.25, 0.3, 0.4, 0.19, 0.45, 0.93, 0.44, 0.65] 
raw_2 = [0.27, 0.39, 0.09, 0.75, 0.79, 0.77, 0.31, 0.05, 0.73, 0.7]
raw_4 = [0.2, 0.84, 0.83, 0.7, 0.86, 0.2, 0.37, 0.41, 0.72, 0.29]
raw_8 = [0.2, 0.71, 0.31, 0.63, 0.24, 0.07, 0.2, 0.89, 0.34, 0.92]
y = np.array([raw_1, raw_2, raw_4, raw_8])
y = np.transpose(y)
y_mean = [mean(raw_1), mean(raw_2), mean(raw_4), mean(raw_8)]
x = [1,2,4,8]
xx = range(len(x))
xxr = [x - 0.1 for x in xx]
plt.plot(xxr, y[0], 'rx')
plt.plot(xxr, y[1], 'rx')
plt.plot(xxr, y[2], 'rx')
plt.plot(xxr, y[3], 'rx')
plt.plot(xxr, y[4], 'rx')
plt.plot(xxr, y[5], 'rx')
plt.plot(xxr, y[6], 'rx')
plt.plot(xxr, y[7], 'rx')
plt.plot(xxr, y[8], 'rx')
plt.plot(xxr, y[9], 'rx')

plt.xticks(xx,x)
leg = plt.legend(loc='upper left');

new_raw_1 = [0.217, 0.206, 0.222, 0.271, 0.212, 0.58, 0.333, 0.463, 0.314, 0.59] 
new_raw_2 = [0.511, 0.537, 0.565, 0.597, 0.527, 0.571, 0.505, 0.541, 0.542, 0.517]
new_raw_4 = [0.662, 0.552, 0.772, 0.436, 0.505, 0.577, 0.313, 0.796, 0.582, 0.574]
new_raw_8 = [0.511, 0.587, 0.591, 0.531, 0.522, 0.549, 0.593, 0.544, 0.552, 0.555]
y = np.array([new_raw_1, new_raw_2, new_raw_4, new_raw_8])
y = np.transpose(y)
y_mean_new = [mean(new_raw_1), mean(new_raw_2), mean(new_raw_4), mean(new_raw_8)]
x = [1,2,4,8]
xx = range(len(x))
xxb = [x + 0.1 for x in xx]
plt.plot(xxb, y[0], 'bo')
plt.plot(xxb, y[1], 'bo')
plt.plot(xxb, y[2], 'bo')
plt.plot(xxb, y[3], 'bo')
plt.plot(xxb, y[4], 'bo')
plt.plot(xxb, y[5], 'bo')
plt.plot(xxb, y[6], 'bo')
plt.plot(xxb, y[7], 'bo')
plt.plot(xxb, y[8], 'bo')
plt.plot(xxb, y[9], 'bo')
plt.plot(xx, y_mean_new, color='C0', marker='D', markersize=10, markerfacecolor='white', label='Avg A')
plt.plot(xx, y_mean, color='C1', marker='H', markersize=10, markerfacecolor='white', label='Avg B')
#plt.xticks(xx,x)
leg = plt.legend()

You could also improve the code a bit by removing duplications (particularly the duplicated import of numpy) and using loops to save repeating yourself:

I've also used unique variable names inside the comprehensions in this version as I think the reuse of x might cause problems in Python 2.7.

import matplotlib.pyplot as plt
import numpy as np

raw_1 = [0.38, 0.49, 0.25, 0.3, 0.4, 0.19, 0.45, 0.93, 0.44, 0.65] 
raw_2 = [0.27, 0.39, 0.09, 0.75, 0.79, 0.77, 0.31, 0.05, 0.73, 0.7]
raw_4 = [0.2, 0.84, 0.83, 0.7, 0.86, 0.2, 0.37, 0.41, 0.72, 0.29]
raw_8 = [0.2, 0.71, 0.31, 0.63, 0.24, 0.07, 0.2, 0.89, 0.34, 0.92]
y = np.array([raw_1, raw_2, raw_4, raw_8])
y = np.transpose(y)
y_mean = [np.mean(raw_1), np.mean(raw_2), np.mean(raw_4), np.mean(raw_8)]
x = [1,2,4,8]
xx = range(len(x))

xxr = [j - 0.1 for j in xx]
for point in y:
    plt.plot(xxr, point, 'rx')

plt.xticks(xx,x)
leg = plt.legend(loc='upper left');

new_raw_1 = [0.217, 0.206, 0.222, 0.271, 0.212, 0.58, 0.333, 0.463, 0.314, 0.59] 
new_raw_2 = [0.511, 0.537, 0.565, 0.597, 0.527, 0.571, 0.505, 0.541, 0.542, 0.517]
new_raw_4 = [0.662, 0.552, 0.772, 0.436, 0.505, 0.577, 0.313, 0.796, 0.582, 0.574]
new_raw_8 = [0.511, 0.587, 0.591, 0.531, 0.522, 0.549, 0.593, 0.544, 0.552, 0.555]
y = np.array([new_raw_1, new_raw_2, new_raw_4, new_raw_8])
y = np.transpose(y)
y_mean_new = [np.mean(new_raw_1), np.mean(new_raw_2), np.mean(new_raw_4), np.mean(new_raw_8)]

xxb = [k + 0.1 for k in xx]
for point in y:
    plt.plot(xxb, point, 'bo')

plt.plot(xx, y_mean_new, color='C0', marker='D', markersize=10, markerfacecolor='white', label='Avg A')
plt.plot(xx, y_mean, color='C1', marker='H', markersize=10, markerfacecolor='white', label='Avg B')

leg = plt.legend()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM