简体   繁体   中英

Can matplotlib produce a log bar-chart with X==0 as a valid data-point?

I'd like to create a bar-chart , where the X axis would include hundred of thousands of data points.

Thus, I need to employ the logarithmic scale . Alas, X == 0 is a valid data-point.
BTW, the Y axis should employ the linear scale (where y are distributions, 0 < Y <= 1 ).

Following is minimal demonstration code :

$ cat stack_example.py 
#!/usr/bin/env python

def test_plot3():
    import pylab as pl

    _graph = {0: 0.25, 1: 0.25, 2: 0.25, 3: 0.25}
    epsilon = 0.00000000001
    x = [ pl.log(k) if k > 0 else pl.log(epsilon) for k in _graph ]
    y = [ _graph[k] for k in _graph ]
    lx = pl.xlabel("in degree (logarithmic scale)")
    ly = pl.ylabel("normalized distribution (0 to 1)")
    tl = pl.title("graph in-degree normalized distribution")
    _width = 1.0 / (len(x) * 5.0)
    pl.bar(x, y, width=_width, log=True)
    pl.xscale('log')
    pl.yscale('linear')
    pl.show()

if __name__ == "__main__":
    test_plot3()

Which produced the following invalid graph (the large blue rectangle on the left seems to be a bug):

半对数条形图

Can you suggest a way to produce a correct bar-chart plot from Python, that will employ the logarithmic scale on the X axis, and the Linear scale on the Y axis, and will accept 0 as a valid x point?

EDIT 1

Based on @Ed's comment, I amended my code to:

#!/usr/bin/env python

def test_plot3():
    import pylab as pl

    _graph = {0: 0.25, 1: 0.25, 2: 0.25, 3: 0.25}
    epsilon = 0.1
    x = [ pl.log(k) if k > 0 else pl.log(epsilon) for k in _graph ]
    y = [ _graph[k] for k in _graph ]
    lx = pl.xlabel("in degree (logarithmic scale)")
    ly = pl.ylabel("normalized distribution (0 to 1)")
    tl = pl.title("graph in-degree normalized distribution")
    _width = 1.0 / (len(x) * 5.0)
    pl.bar(x, y, width=_width, color="blue", log=True)
    pl.xscale('symlog', linthreshx=2)
    pl.yscale('linear')
    pl.show()

if __name__ == "__main__":
    test_plot3()


    if __name__ == "__main__":
        test_plot3()

but the resulting graph still doesn't seem right:

修正图

You can use symlog instead of log, which includes negaive numbers and a small linear region near zero. For your example,

#!/usr/bin/env python

def test_plot3():
    import pylab as pl

    _graph = {0: 0.25, 1: 0.25, 2: 0.25, 3: 0.25}
    epsilon = 0.00000000001
    x = [ pl.log(k) if k > 0 else pl.log(epsilon) for k in _graph ]
    y = [ _graph[k] for k in _graph ]
    lx = pl.xlabel("in degree (logarithmic scale)")
    ly = pl.ylabel("normalized distribution (0 to 1)")
    tl = pl.title("graph in-degree normalized distribution")
    _width = 1.0 / (len(x) * 5.0)
    pl.bar(x, y, width=_width, log=True)
    pl.xscale('symlog')
    pl.yscale('linear')
    pl.show()

if __name__ == "__main__":
    test_plot3()

You can tune the size of the linear region with linthreshx argument to xscale . Check out this question for details on how to use it.

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