0

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:

I need the orignal values in Y axis

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?

5
  • What values do you want on the y axis? Commented Sep 22, 2017 at 23:32
  • @wwii: I need to show all the real values:3,195,200,...203 Commented Sep 22, 2017 at 23:34
  • @wwii: Is that possible using log scale? Commented Sep 22, 2017 at 23:34
  • Numbers like 210, 220, 230, and 240 are so close together on a log scale that their text would probably overlap. Commented Sep 22, 2017 at 23:45
  • @wwii: So, I would like to show the maximum number of values! Commented Sep 22, 2017 at 23:47

4 Answers 4

4

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but It did not show all the real values: 263,170 ... in Y axis. Is that possible? -> ufile.io/lzxbc
I feel those would be better shown on the bars themselves, matplotlib gives a good example bar chart which might help
thanks. Could you help to show the real values in the Y axis? I think it would be better!
Seems much more involved, will take a look in the morning if nobody has a solution by then
4

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()

enter image description here

Comments

2

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)])

1 Comment

After reviewing this answer, the question and the other answers, I'm wondering why it got accepted.
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.