Sku*_*kum 7 python matplotlib python-3.x pandas
我有一些来自亚马逊的数据,我想对其进行处理。我想包含的图之一是每个品牌的评分分布,我认为最好的方法是堆叠条形图。
但是,有些品牌的评论比其他品牌要多得多,所以我必须使用对数刻度,否则情节将是 3 个峰值,而其他品牌将无法正常看到。
大约有 300'000 个看起来像这样
reviewID brand overall
0 Logitech 5.0
1 Garmin 4.0
2 Logitech 4.0
3 Logitech 5.0
Run Code Online (Sandbox Code Playgroud)
我用过这个代码
brandScore = swissDF.groupby(['brand', 'overall'])['brand']
brandScore = brandScore.count().unstack('overall')
brandScore.plot(kind='bar', stacked=True, log=True, figsize=(8,6))
Run Code Online (Sandbox Code Playgroud)
这就是结果
现在,如果您不熟悉这些数据,这看起来可能是可以接受的,但实际上并非如此。与其他评分相比,1.0 评分堆栈看起来太大了,因为对数在该范围内并不是“完全有效”,而是会处理更好的分数。有没有办法在对数图上线性表示评分分布?
我的意思是,如果 60% 的评分是 5.0,那么 60% 的条应该是粉红色的,而不是我现在拥有的
为了使总条高度处于对数尺度上,但条内类别的比例是线性的,可以重新计算堆叠数据,使其在对数尺度上呈现线性。
作为展示示例,让我们选择 6 个总计差异很大的数据集 ( [5,10,50,100,500,1000]
),这样在线性比例上,下部条形图会非常小。在本例中,我们将其分为 30%、50% 和 20%(为简单起见,所有不同的数据均按相同的比例划分)。
然后,我们可以计算稍后出现在堆叠条上的每个数据点需要有多大,以便 30%、50% 和 20% 的比率保留在对数比例图中,最后绘制新创建的数据点数据。
from __future__ import division
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
a = np.array([5,10,50,100,500,1000])
p = [0.3,0.5,0.2]
c = np.c_[p[0]*a,p[1]*a, p[2]*a]
d = np.zeros(c.shape)
for j, row in enumerate(c):
g = np.zeros(len(row)+1)
G = np.sum(row)
g[1:] = np.cumsum(row)
f = 10**(g/G*np.log10(G))
f[0] = 0
d[j, :] = np.diff( f )
collabels = ["{:3d}%".format(int(100*i)) for i in p]
dfo = pd.DataFrame(c, columns=collabels)
df2 = pd.DataFrame(d, columns=collabels)
fig, axes = plt.subplots(ncols=2)
axes[0].set_title("linear stack bar")
dfo.plot.bar(stacked=True, log=False, ax=axes[0])
axes[0].set_xticklabels(a)
axes[1].set_title("log total barheight\nlinear stack distribution")
df2.plot.bar(stacked=True, log=True, ax=axes[1])
axes[1].set_xticklabels(a)
axes[1].set_ylim([1, 1100])
plt.show()
Run Code Online (Sandbox Code Playgroud)
最后说一句:我认为人们应该小心对待这样的情节。它可能对检查有用,但我不建议向其他人展示这样的图,除非可以绝对确保他们理解绘制的内容以及如何阅读它。否则这可能会引起很多混乱,因为堆叠类别的高度与比例不匹配,这根本就是错误的。显示虚假数据可能会造成很多麻烦!
归档时间: |
|
查看次数: |
3877 次 |
最近记录: |