python - Python:根据第三个变量着色的条形图
问题描述
目前我正在尝试创建一个 Barplot 来显示每周应用程序的评论量。然而,该条应根据第三个变量着色,该变量包含每周评论的平均评分(范围:1 到 5)。
我按照以下帖子的说明创建了图表:Python: Barplot with colorbar
代码工作正常:
# Import Packages
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
# Create Dataframe
data = [[1, 10, 3.4], [2, 15, 3.9], [3, 12, 3.6], [4, 30,1.2]]
df = pd.DataFrame(data, columns = ["week", "count", "score"])
# Convert to lists
data_x = list(df["week"])
data_hight = list(df["count"])
data_color = list(df["score"])
#Create Barplot:
data_color = [x / max(data_color) for x in data_color]
fig, ax = plt.subplots(figsize=(15, 4))
my_cmap = plt.cm.get_cmap('RdYlGn')
colors = my_cmap(data_color)
rects = ax.bar(data_x, data_hight, color=colors)
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(1,5))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Color', rotation=270,labelpad=25)
plt.show()
现在问题来了:您可能会注意到第 4 周的平均分数是“1.2”。然而,条形图确实表明该值位于“2.5”左右。我知道这源于以下代码行,它通过将值除以最大值来标准化值:
data_color = [x / max(data_color) for x in data_color]
不幸的是,我无法以颜色与分数的绝对值相似的方式更改此命令,例如,平均分数为 1.2,最后一个条形应为深红色而不是浅橙色。我试图只插入常规分数值(未标准化)来解决问题,但是,这样做会创建所有具有相同绿色的条...由于这只是我的第二个 python 项目,我很难理解这件事背后的过程,非常感谢您提供任何建议或解决方案。
干杯尼尔
解决方案
您正确地确定了标准化是这里的问题。它位于链接代码中,由有价值的 SO 用户 @ImportanceOfBeingEarnest 为区间定义[0, 1]
。如果你想要另一个归一化范围[normmin, normmax]
,你必须在归一化过程中考虑到这一点:
# Import Packages
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
# Create Dataframe
data = [[1, 10, 3.4], [2, 15, 3.9], [3, 12, 3.6], [4, 30,1.2]]
df = pd.DataFrame(data, columns = ["week", "mycount", "score"])
# Not necessary to convert to lists, pandas series or numpy array is also fine
data_x = df.week
data_hight = df.mycount
data_color = df.score
#Create Barplot:
normmin=1
normmax=5
data_color = [(x-normmin) / (normmax-normmin) for x in data_color] #see the difference here
fig, ax = plt.subplots(figsize=(15, 4))
my_cmap = plt.cm.get_cmap('RdYlGn')
colors = my_cmap(data_color)
rects = ax.bar(data_x, data_hight, color=colors)
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(normmin,normmax))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Color', rotation=270,labelpad=25)
plt.show()
样本输出:
显然,这并不能检查所有值是否确实在 range 内[normmin, normmax]
,因此更好的脚本会确保所有值都符合此规范。或者,我们可以通过裁剪超出规范化范围的值来解决这个问题:
#...
import numpy as np
#.....
#Create Barplot:
normmin=1
normmax=3.5
data_color = [(x-normmin) / (normmax-normmin) for x in np.clip(data_color, normmin, normmax)]
#....
您可能还注意到我介绍的另一个变化。您不必提供列表 - pandas 系列或 numpy 数组也可以。如果您将列命名为不像 pandas 函数,例如count
,您可以访问它们df.ABC
而不是df["ABC"]
.
推荐阅读
- python - Pip 安装二进制文件并保留 requirements.txt
- css - 当有换行符时,如何在折叠中显示我的导航栏?
- scala - 如何创建具有特定版本的 Play 项目?
- awk - 如何使用 sed 仅打印文件中紧接在空行之前的行?
- ruby-on-rails - 使用 rbenv 或 rvm 在 Mojave OSX 上安装 Ruby 2.3.1
- iis - IIS 中的本地 VS 继承页面
- postman - 尝试更新松弛频道上的主题时,我得到`method_not_supported_for_channel_type`
- django - 如何使用django-ckeditor为不同的模型指定不同的图片上传路径?
- python - 当 C++ 程序正在读取文件而单独的 python GUI 脚本正在写入同一文件时,会发生分段错误
- jquery - 让两个奇怪大小的元素响应地位于想象容器的中心和边缘