我有一些来自亚马逊的数据,我想参与其中。我想要包括的一个情节是每个品牌的评级分布,我认为这样做的最佳方式是堆积条形图。
然而,有些品牌比其他品牌更受欢迎,所以我必须使用对数刻度,否则情节将是3个峰值,其他品牌将无法正常看待。
有大约300个' 000 entires看起来像这样
reviewID brand overall
0 Logitech 5.0
1 Garmin 4.0
2 Logitech 4.0
3 Logitech 5.0
我已使用此代码
brandScore = swissDF.groupby(['brand', 'overall'])['brand']
brandScore = brandScore.count().unstack('overall')
brandScore.plot(kind='bar', stacked=True, log=True, figsize=(8,6))
这是结果
现在,如果您不熟悉数据,这可能看起来可以接受,但实际上并非如此。 1.0评级堆栈看起来与其他堆栈相比太大,因为对数不是完全有效的"在那个范围内但是会收获更好的分数。 有没有办法在对数图上线性表示评级分布?
我的意思是,如果60%的评分是5.0,那么60%的标准应该是粉红色,而不是我现在拥有的
答案 0 :(得分:2)
为了使总条形高度以对数刻度生存,但条形内的类别比例是线性的,可以重新计算堆积数据,使其在对数刻度上呈线性。
作为一个展示示例,让我们选择具有非常不同的总数([5,10,50,100,500,1000]
)的6个数据集,这样在线性比例上,较低的条形将会很小。在这种情况下,我们将它分成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()
最后一句话:我认为应该小心这样的情节。它可能对检查有用,但我不建议向其他人展示这样的情节,除非人们可以绝对确定他们理解绘制的内容以及如何阅读它。否则这可能会引起很多混乱,因为堆积的类别'高度与简单错误的比例不匹配。并且显示错误数据会导致很多麻烦!
答案 1 :(得分:1)
答案 2 :(得分:1)
没有数据的两条建议(提供样本数据更好)
选项1
使用value_counts(normalize=True)
brandScore = swissDF.groupby(['brand', 'overall'])['brand']
brandScore = brandScore.value_counts(normalize=True).unstack('overall')
brandScore.plot(kind='bar', stacked=True, figsize=(8,6))
选项2
除以行和
brandScore = swissDF.groupby(['brand', 'overall'])['brand']
brandScore = brandScore.count().unstack('overall')
brandScore.div(brandScore.sum(1), 0).plot(kind='bar', stacked=True, figsize=(8,6))