3

I have 2 lists, each has 128 elements

x = [1,2,3,...,128]
y = [y1,y2,...,y128]

How should I use matplotlib to plot (x,y) with x axis appearing as shown in this screenshot?

To replicate the graph, I have (1) created 2 additional lists from the original lists, and (2) used set_xticklabels:

f, ax1 = plt.subplots(1,1,figsize=(16,7))  
x1 = [1, 2, 4, 8, 16, 32, 64, 128]  
y1 = [y[0],y[1],y[3],y[7],y[15],y[31],y[63],y[127]]  

line1 = ax1.plot(x1,y1,label="Performance",color='b',linestyle="-")  

ax1.set_xticklabels([0,1,2,4,8,16,32,64,128])  
ax1.set_xlabel('Time Period',fontsize=15)  
ax1.set_ylabel("Value",color='b',fontsize=15)

The problem with this approach is that only 8 pairs of value are plotted, and 120 pairs are ommitted.

IMCoins
  • 3,149
  • 1
  • 10
  • 25
DT Ngo
  • 31
  • 1
  • 4
  • Have you tried [xticks](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.xticks.html?highlight=colorbar%20tick%20labelling%20demo#matplotlib-pyplot-xticks) and [yticks](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.yticks.html?highlight=colorbar%20tick%20labelling%20demo#matplotlib-pyplot-yticks)? – Sohaib Farooqi Feb 26 '18 at 09:58
  • What is the code you used to get this image ? Doesn't using a function such as `plt.plot(x, f(x))` would be sufficient ? – IMCoins Feb 26 '18 at 09:59
  • 1
    @ IMCoins using plt.plot(x, f(x)) is not sufficient because the interval of my x axis is uneven. I know how to show 8 points on my graph, but what i am asking for is how to show 128 data points while still having the x axis as shown in the attached screenshot. – DT Ngo Feb 26 '18 at 10:15
  • Possible duplicate of [making square axes plot with log2 scales in matplotlib](https://stackoverflow.com/questions/8887544/making-square-axes-plot-with-log2-scales-in-matplotlib) – SiHa Feb 26 '18 at 12:01

2 Answers2

1

If my comments aren't clear enough, please, ask. :)

from matplotlib import pyplot as plt

#   Instanciating my lists...
f = lambda x:x**2
x = [nb for nb in range(1, 129)]
y = [f(nb) for nb in x]

#   New values you want to plot, with linear spacing.
indexes_to_keep = [1, 2, 4, 8, 16, 32, 64, 128]
y_to_use = [y[nb - 1] for nb in indexes_to_keep]

#   First plot that shows the 128 points as a whole.
fig = plt.figure(figsize=(10, 5.4))
ax1 = fig.add_subplot(121)
ax1.plot(x, y)
ax1.set_title('Former values')

#   Second plot that shows only the indexes you wish to keep.
ax2 = fig.add_subplot(122)

#   my_ticks = [1, 2, 3, 4, 5, 6, 7]
#   meaning : my_ticks will be linear values.
my_ticks = [i for i in range(len(indexes_to_keep))]

#   We set the ticks we want to show, meaning : all our list
#   instead of some linear spacing matplotlib will show by default
ax2.set_xticks(my_ticks)

#   Then, we manually change the name of the X ticks.
ax2.set_xticklabels(indexes_to_keep)

#   We will then, plot the LINEAR x axis,
#   but with respect to the y-axis values pre-processed.
ax2.plot(my_ticks, y_to_use)
ax2.set_title('New selected values with linear spacing')

plt.show()

Showing...

Imgur

IMCoins
  • 3,149
  • 1
  • 10
  • 25
  • I had similar need where my x axis items were `datetime` objects. As in this question my dates weren't separated regularly. First I was doing this: `plt.bar(hours, frequency)` where `hours` is list of `datetime` objects and this was plotting values like left graph, keeping the x ticks at regular intervals. Most of the y-values were 0 because of this regular spacing. I just changed the x axis items to be string: `plt.bar([h.isoformat() for h in hours], frequency)` and then it put only those dates as ticks that were present in the list, instead of doing any regular spacing. This solved my case. – Vikas Prasad Apr 09 '19 at 06:29
0

What you are looking for is a logarithmic scale with base 2. matplotlib provides logarithmic scales and you can define any base you want:

from matplotlib import pyplot as plt
from matplotlib.ticker import ScalarFormatter
#sample data
x = list(range(1, 130))
y = list(range(3, 260, 2)) 

f, ax1 = plt.subplots(1,1,figsize=(16,7))
x1 = [  1,   2,   4,   8,   16,   32,   64,   128]
y1 = [y[0],y[1],y[3],y[7],y[15],y[31],y[63],y[127]]
#just the points, where the ticks are
ax1.plot(x1, y1,"bo-", label = "Performance")
#all other points to contrast this
ax1.plot(x, [270 - i for i in y], "rx-", label = "anti-Performance")
#transform x axis into logarithmic scale with base 2
plt.xscale("log", basex = 2)
#modify x axis ticks from exponential representation to float 
ax1.get_xaxis().set_major_formatter(ScalarFormatter())
ax1.set_xlabel('Time Period',fontsize=15)
ax1.set_ylabel("Value",color='b',fontsize=15)
plt.legend()
plt.show()

Output:

enter image description here

Mr. T
  • 11,960
  • 10
  • 32
  • 54