Reputation: 1337
I am Trying to plot a graphic in logarithmic scale (Y axis) but I need to show in the Y axis all the original values.
I used the code:
# -*- coding: utf-8 -*-
import math
import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime, timedelta
import numpy as np
x = []
y = []
with open("dataset.csv") as f:
for l in f:
X,Y = l.split(",") #separador eh a virgula
x.append(float(X))
y.append( float (Y))
#y.append( math.log (float (Y)))
#x1 = [datetime.fromtimestamp(int(d)) for d in x]
x1 = [str(datetime.fromtimestamp(int(d)))[-8:] for d in x]
y_pos = [idx for idx, i in enumerate(y)]
plt.figure(figsize=(17,9))
plt.gca().xaxis.set_major_formatter(dates.DateFormatter('%m/%d/%Y %H:%M:%S'))
plt.bar(y_pos, y, align='edge', color="blue", alpha=0.5, width=0.5) # <--- EDICAO PRINCIPAL
plt.title("Values X Time")
plt.ylabel("Values")
plt.xlabel('Time')
plt.xticks(y_pos, x1, size='small',rotation=35, ha="right")
#plt.yticks(y)
#plt.yticks(np.arange(0,max(y),0.3))
#plt.yticks(np.arange(0,max(y)+5,1))
plt.yscale('log')
plt.ylim(ymax=sorted(y)[-1]+1) # valor maximo do eixo y
#plt.ylim(ymin=sorted(y)[0]-1) # valor minimo do eixo y
plt.show()
Where dataset is:
1491828000,3
1491828060,195
1491828120,220
1491828180,240
1491828240,230
1491828300,238
1491828360,310
1491828420,280
1491828480,263
1491828540,271
1491828600,282
1491828660,302
1491828720,298
1491828780,257
1491828840,245
1491828900,200
1491828960,170
1491829020,138
1491829080,59
1491829140,39
1491829200,48
1491829260,95
1491829320,151
1491829380,155
1491829440,175
1491829500,93
1491829560,25
1491829620,3
1491829680,185
1491829740,233
1491829800,210
1491829860,86
1491829920,32
1491829980,46
1491830040,51
1491830100,201
1491830160,129
1491830220,116
1491830280,105
1491830340,200
1491830400,203
But the result is:
How could I show the original values in Y axis (logarithmic scale ), instead of 10, 10², etc? I tried hard but I only could show 10, 10² in Y axis!
I need to show in the Y axis all the original values. Any idea?
Upvotes: 0
Views: 28729
Reputation: 541
Funny, I solved exactly this problem in the SO in portuguese.
In addition to the answer of ImportanceOfBeingErnest, you can add
plt.gca().minorticks_off()
to remove the minor ticks of the log scale, as they are overlapping. As i believe that this remove all minor ticks, you can use another approach:
matplotlib.rcParams['xtick.minor.size'] = 0
matplotlib.rcParams['xtick.minor.width'] = 0
Or any of the other solutions mentioned in this question.
Upvotes: 2
Reputation: 339102
The question seems to be how to show all y values which are present as bars on the y axis, given the y axis being a logarithmic scale.
While this may not make too much sense, because of overlapping labels, here is the answer:
You may use a FixedLocator
to set the positions of the labels and a ScalarFormatter
to set the format to normal decimal numbers (instead of powers of 10).
plt.gca().yaxis.set_major_locator(matplotlib.ticker.FixedLocator(np.unique(y))) plt.gca().yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
Complete code:
import matplotlib.pyplot as plt
import matplotlib.dates as dates
import matplotlib.ticker
from datetime import datetime, timedelta
import numpy as np
x,y = np.loadtxt(io.StringIO(u), delimiter=",", unpack=True)
x1 = [str(datetime.fromtimestamp(int(d)))[-8:] for d in x]
y_pos = [idx for idx, i in enumerate(y)]
plt.figure(figsize=(17,9))
plt.gca().xaxis.set_major_formatter(dates.DateFormatter('%m/%d/%Y %H:%M:%S'))
plt.bar(y_pos, y, align='edge', color="blue", alpha=0.5, width=0.5)
plt.title("Values X Time")
plt.ylabel("Values")
plt.xlabel('Time')
plt.xticks(y_pos, x1, size='small',rotation=35, ha="right")
plt.yscale('log')
plt.ylim(ymax=sorted(y)[-1]+1) # valor maximo do eixo y
plt.gca().yaxis.set_major_locator(matplotlib.ticker.FixedLocator(np.unique(y)))
plt.gca().yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
plt.show()
Upvotes: 4
Reputation: 23743
You can specify ether the x or y tick locations. To add the maximum value to the y axis use .yticks()
.
plt.yscale('log')
plt.yticks([1,10,100] + [max(y)])
plt.gca().yaxis.set_major_formatter(FormatStrFormatter('%.d'))
To determine the major ticks for a log scale at runtime; find the maximum power of ten in the data, then make all the powers of ten below it.:
import math
...
exp = int(math.log10(max(y)))
majors = [10**x for x in range(exp+1)]
#majors = [10**n for n in range(len(str(max(y))))]
plt.yticks(majors + [max(y)])
Upvotes: 2
Reputation: 167
Matplotlib ticker formatting is what you're looking for:
from matplotlib.ticker import FormatStrFormatter
...
plt.yscale('log')
plt.gca().yaxis.set_major_formatter(FormatStrFormatter('%.d')) #Here!
plt.ylim(ymax=sorted(y)[-1]+1) # valor maximo do eixo y
plt.show()
Though there may be a simpler way. Found using matplotlibs tick formatting documentation
Upvotes: 4