我想修改下面指示的绘图的 Y 轴单位。对于大数,最好使用M(百万)、k(千)等单位。例如,y 轴应如下所示:50k、100k、150k 等。
下图由以下代码片段生成:
plt.autoscale(enable=True, axis='both')
plt.title("TTL Distribution")
plt.xlabel('TTL Value')
plt.ylabel('Number of Packets')
y = graphy # data from a sqlite query
x = graphx # data from a sqlite query
width = 0.5
plt.bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red')
fig = plt.gcf()
plt.show()
Run Code Online (Sandbox Code Playgroud)
我看到这篇文章,并认为我可以编写自己的格式化函数:
def y_fmt(x, y):
if max_y > 1000000:
val = int(y)/1000000
return '{:d} M'.format(val)
elif max_y > 1000:
val = int(y) / 1000
return '{:d} k'.format(val)
else:
return y
Run Code Online (Sandbox Code Playgroud)
但我错过了plt.yaxis.set_major_formatter(tick.FuncFormatter(y_fmt))我正在使用的条形图没有可用的功能。
如何更好地格式化 Y 轴?
[
]
Imp*_*est 11
原则上,始终可以选择通过plt.gca().yaxis.set_xticklabels().
但是,我不确定为什么不能在matplotlib.ticker.FuncFormatter这里使用。该FuncFormatter设计用于提供取决于ticklabel的地位和价值的定制ticklabels的确切目的。matplotlib 示例集合中实际上有一个很好的示例。
在这种情况下,我们可以根据需要使用 FuncFormatter 来提供单位前缀作为 matplotlib 图轴上的后缀。为此,我们迭代 1000 的倍数,并检查要格式化的值是否超过它。如果该值是一个整数,我们可以将其格式化为整数,并以相应的单位符号为后缀。另一方面,如果小数点后面有余数,我们检查需要多少个小数位来格式化这个数字。
这是一个完整的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
def y_fmt(y, pos):
decades = [1e9, 1e6, 1e3, 1e0, 1e-3, 1e-6, 1e-9 ]
suffix = ["G", "M", "k", "" , "m" , "u", "n" ]
if y == 0:
return str(0)
for i, d in enumerate(decades):
if np.abs(y) >=d:
val = y/float(d)
signf = len(str(val).split(".")[1])
if signf == 0:
return '{val:d} {suffix}'.format(val=int(val), suffix=suffix[i])
else:
if signf == 1:
print val, signf
if str(val).split(".")[1] == "0":
return '{val:d} {suffix}'.format(val=int(round(val)), suffix=suffix[i])
tx = "{"+"val:.{signf}f".format(signf = signf) +"} {suffix}"
return tx.format(val=val, suffix=suffix[i])
#return y
return y
fig, ax = plt.subplots(ncols=3, figsize=(10,5))
x = np.linspace(0,349,num=350)
y = np.sinc((x-66.)/10.3)**2*1.5e6+np.sinc((x-164.)/8.7)**2*660000.+np.random.rand(len(x))*76000.
width = 1
ax[0].bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red')
ax[0].yaxis.set_major_formatter(FuncFormatter(y_fmt))
ax[1].bar(x[::-1], y*(-0.8e-9), width, align='center', linewidth=2, color='orange', edgecolor='orange')
ax[1].yaxis.set_major_formatter(FuncFormatter(y_fmt))
ax[2].fill_between(x, np.sin(x/100.)*1.7+100010, np.cos(x/100.)*1.7+100010, linewidth=2, color='#a80975', edgecolor='#a80975')
ax[2].yaxis.set_major_formatter(FuncFormatter(y_fmt))
for axes in ax:
axes.set_title("TTL Distribution")
axes.set_xlabel('TTL Value')
axes.set_ylabel('Number of Packets')
axes.set_xlim([x[0], x[-1]+1])
plt.show()
Run Code Online (Sandbox Code Playgroud)
它提供了以下情节:
你们已经很接近了;一个(可能)令人困惑的事情FuncFormatter是,第一个参数是刻度值,第二个参数是刻度位置,(当命名时x,y)可能会混淆 y 轴。为了清楚起见,我在下面的示例中重命名了它们。
该函数应接受两个输入(刻度值 x 和位置 pos)并返回一个字符串
(http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.FuncFormatter)
工作示例:
import numpy as np
import matplotlib.pylab as pl
import matplotlib.ticker as tick
def y_fmt(tick_val, pos):
if tick_val > 1000000:
val = int(tick_val)/1000000
return '{:d} M'.format(val)
elif tick_val > 1000:
val = int(tick_val) / 1000
return '{:d} k'.format(val)
else:
return tick_val
x = np.arange(300)
y = np.random.randint(0,2000000,x.size)
width = 0.5
pl.bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red')
pl.xlim(0,300)
ax = pl.gca()
ax.yaxis.set_major_formatter(tick.FuncFormatter(y_fmt))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14441 次 |
| 最近记录: |