我有一张CDF图,其中包含以MB为单位的wifi使用情况。为了更好地理解,我想提出以KB开头并以TB结束的用法。我想知道如何设置x轴的特定范围来替换plt.plot()的产品,并将轴x显示为[1KB 10KB 1MB 10MB 1TB 10TB],甚至是不代表的箱之间的空间真正的价值观。
我现在的代码:
wifi = np.sort(matrix[matrix['wifi_total_mb']>0]['wifi_total_mb'].values)
g = sns.distplot(wifi, kde_kws=dict(cumulative=True))
plt.show()
由于
编辑1
我知道我可以使用plt.xticks
,我已经尝试过了:plt.xticks([0.00098, 0.00977, 1, 10, 1024, 10240, 1048576, 10485760, 24117248])
。这些是以MB为单位的值,表示我之前指定的样本范围。但情节仍然是错误的。
预期结果
在excel中,很容易实现我想要的东西。看看图像,我得到了我想要的情节,范围相同。
由于
答案 0 :(得分:3)
计算要手动绘制的数据可能更好,而不是依赖于某些seaborn辅助函数,如distplot
。这也使得更容易理解具有非常不相等的箱尺寸的直方图的基本问题。
可以使用np.histogram()
计算数据的直方图。它可以将所需的箱子作为参数
为了获得累积直方图,np.cumsum
完成了这项工作。
现在有两个选项:(a)绘制真实数据或(b)绘制bin枚举的数据。
由于bin大小非常不相等,因此对数缩放似乎已足够,可以通过semilogx(x,y)
来完成。 bin边缘可以使用set_xticks
显示为xticks(并且由于semilogx图不会自动正确设置标签,我们还需要将它们设置为bin边缘的值)。
第二个选项是逐个绘制直方图值,而不依赖于实际的容器大小。是非常接近问题的Excel解决方案。在这种情况下,绘图的x值只是从0到bin数的值,而xticklabels是bin边缘。
以下是完整的代码:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#use the bin from the question
bins = [0, 0.00098, 0.00977, 1, 10, 1024, 10240, 1048576, 10485760, 24117248]
# invent some data
data = np.random.lognormal(2,4,10000)
# calculate histogram of the data into the given bins
hist, _bins = np.histogram(data, bins=bins)
# make histogram cumulative
cum_hist=np.cumsum(hist)
# normalize data to 1
norm_cum_hist = cum_hist/float(cum_hist.max())
fig, (ax, ax2) = plt.subplots(nrows=2)
plt.subplots_adjust(hspace=0.5, bottom=0.17)
# First option plots the actual data, i.e. the bin width is reflected
# by the spacing between values on x-axis.
ax.set_title("Plotting actual data")
ax.semilogx(bins[1:],norm_cum_hist, marker="s")
ax.set_xticks(bins[1:])
ax.set_xticklabels(bins[1:] ,rotation=45, horizontalalignment="right")
# Second option plots the data bin by bin, i.e. every bin has the same width,
# independent of it's actual value.
ax2.set_title("Plotting bin by bin")
ax2.plot(range(len(bins[1:])),norm_cum_hist, marker="s")
ax2.set_xticks(range(len(bins[1:])))
ax2.set_xticklabels(bins[1:] ,rotation=45, horizontalalignment="right")
for axes in [ax, ax2]:
axes.set_ylim([0,1.05])
plt.show()