Logarithmic Scale Chart with Python

1

Initially I created a chart of Values X time (time in Unix Time) with the following code:

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime, timedelta

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

#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("ValoresX TEMPO")
plt.ylabel("Valores")
plt.xlabel('Tempo')
plt.xticks(y_pos, x1, size='small',rotation=35, ha="right")
plt.yticks(y)
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()

Whose graphic is generated:

Overlappingvaluescanbeseen.Theideaistousealogarithmicscaletoimprovethegraph,sowecancomparethevaluesbetter.ForthisIused:plt.yscale('log')Thus:

#-*-coding:utf-8-*-importmathimportmatplotlib.pyplotaspltimportmatplotlib.datesasdatesfromdatetimeimportdatetime,timedeltaimportnumpyasnpx=[]y=[]withopen("dataset.csv") as f:
    for l in f:
        X,Y = l.split(",") #separador eh a virgula
        x.append(float(X))
        y.append( 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("Valores X Tempo")
plt.ylabel("Valores")
plt.xlabel('Tempo')
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,10))
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.yscale('log')
plt.show()

The new graphic looked like this:

And it was horrible. Any idea how to make a better graph on a logarithmic scale on the y-axis, but displaying the original values on the graph? The 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

Any idea how to make a better graph in logarithmic scale on the y-axis, but displaying the original values in the graph?

    
asked by anonymous 22.09.2017 / 17:14

1 answer

2

The problem is the call order.

Call plt.yscale('log') and then call plt.ylim(ymax=sorted(y)[-1]+100,ymin=sorted(y)[0]-1) .

See that I have added 100 to the maximum value, due to the log scale. If you want the bar just right at the top, you can use a lower value. To get a good spacing between the top of the bars and the graph border, similar to the linear scale, a large value is needed, to be more specific an order of magnitude greater.

I also noticed that according to the yticks call, you may have similar problems. But it always seems to call up the automatic values, which have a great presentation. Remember that you should warn the graph reader that this scale is logarithmic, and the best way to do this is with ticked ticks . matplotlib.ticker has a specific function to adjust the ticks in the log scale if the original values are not to your liking. If you want to put ticks with the original values - that overlap and do not go well with the idea of the logarithm - there are some questions in SO original that do this . The code below when placed after the declaration of limits mentioned above does the work:

import matplotlib.ticker # vai para as primeiras linhas

ymajorLocator = matplotlib.ticker.FixedLocator(locs=y) 
ymajorFormatter = matplotlib.ticker.ScalarFormatter()
plt.gca().yaxis.set_major_locator( ymajorLocator )
plt.gca().yaxis.set_major_formatter( ymajorFormatter )
plt.gca().minorticks_off()

See that I took all minorticks for being the fastest. There are better solutions in the answers mentioned above, but they do require a lot of time to see exactly what's best: a decent chart takes time.

Aliases, you can give a incremented in your chart: P.

Edit 1 and 2: Explanation of log & ticks, respectively.

    
22.09.2017 / 19:05