python - 自动设置 matplotlib 范围的 Y 限制
问题描述
我被要求使用 seaborn 绘制一些直方图和 KDE。我们只想关注 X 轴的范围,所以我使用ax.set_xlim(20_000, 42_460)
. 在某些情况下,大多数数据都在 20.000 之前,因此该图如下所示:
完整的情节如下所示:
有数据,但由于大部分都在 (0,20.000) 范围内,matplotlib 将 Y 限制调整到它,并且在 (20.000, 42.460) 范围内,数据无法被欣赏。
我想知道一种自动调整 Y 限制的方法,以便范围 (20.000, 42.460) 中的数据可见。我被要求不要只绘制范围(20.000、42.460),我必须绘制范围(0、42.460)然后放大范围(20.000、42.460)。
我发现Axes.relim()
这可以争论visible_only=True
,但它似乎没有像我预期的那样工作。
其他选项可能是使用不同的库来计算直方图数据,然后计算 Y 限制并设置它,ax.set_ylim(0, range_max)
但我们也在绘制具有相同问题并且可能更复杂的 seaborn KDE。这是一个很好的情节的形象:
编辑:
要重现该图,请使用此数据和此代码:
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
ages = {
'25-34':'blue',
'35-44': 'orange',
'45-54': 'green',
'55-64': 'red',
}
markers = [plt.Line2D([0,0],[0,0],color=color, marker='o', linestyle='') for color in ages.values()]
data = pd.read_csv("./data.csv")
min = 20_000
max = 42_460
fig = plt.figure(figsize=(10,11))
fig.suptitle("Title", fontsize=12)
fig.legend(markers, ages.keys(),loc='center right')
gs = fig.add_gridspec(3, hspace=0, height_ratios=[5,1,5])
axs = gs.subplots(sharex=True, sharey=False)
sns.histplot(data=data, x="data", bins=200,ax=axs[0])
#axs[1].plot([pos[0] for pos in m1.elevation], [pos[1] for pos in m1.elevation])
sns.kdeplot(data=data, x="data", hue="labels",
common_norm=False,bw_adjust=.25,ax=axs[2]
,legend=False, palette=ages.values(), hue_order=ages.keys())
plt.rcParams['xtick.bottom'] = plt.rcParams['xtick.labelbottom'] = True
plt.rcParams['xtick.top'] = plt.rcParams['xtick.labeltop'] = False
axs[0].set_axisbelow(True)
axs[0].set_xlim(min, max)
axs[0].grid(b=True, which='minor', color='#eeeeee90',lw=0.5)
axs[0].grid(b=True, which='major', color='#cccccc20',lw=0.8)
axs[0].relim(visible_only=True)
axs[1].set_ylim(0, 40)
axs[1].set_xticks(np.arange(min, max, 2500))
axs[1].set_xticks(np.arange(min, max, 500), minor=True)
axs[1].grid(b=True, which='minor', color='#eeeeee90',lw=0.5)
axs[1].grid(b=True, which='major', color='#cccccc20',lw=0.8)
axs[2].set_axisbelow(True)
axs[2].set_xlim(min, max)
axs[2].grid(b=True, which='minor', color='#eeeeee90',lw=0.5)
axs[2].grid(b=True, which='major', color='#cccccc20',lw=0.8)
中间的情节已被省略,因为它不有趣并且使代码更简单。
解决方案
实现你想要的最快的方法是对你的 DataFrame 进行子集化:
# I've renamed these as they override the builtin min/max
min_ = 20_000
max_ = 42_460
# `mask` is an array of True/False that allows
# us to select a subset of the DataFrame
mask = data["data"].between(min_, max_, inclusive=True)
plot_data = data[mask]
如果您设置cut=0
在es 上,sns.kdeplot
则不需要xlim
为ax
es 设置,但这可能会截断一些行。我把它排除在外是因为我认为没有它看起来会更好。
此外,当您在子图上使用sharex
时,我认为您只需要调用set_xlim
一次。
然后用于plot_data
绘制图表:
ages = {"25-34": "blue", "35-44": "orange", "45-54": "green", "55-64": "red"}
markers = [
plt.Line2D([0, 0], [0, 0], color=color, marker="o", linestyle="")
for color in ages.values()
]
fig = plt.figure(figsize=(10, 11))
fig.suptitle("Title", fontsize=12)
fig.legend(markers, ages.keys(), loc="center right")
gs = fig.add_gridspec(3, hspace=0, height_ratios=[5, 1, 5])
axs = gs.subplots(sharex=True, sharey=False)
sns.histplot(data=plot_data, x="data", bins=200, ax=axs[0])
sns.kdeplot(
data=plot_data,
x="data",
hue="labels",
common_norm=False,
bw_adjust=0.25,
ax=axs[2],
legend=False,
palette=ages.values(),
hue_order=ages.keys(),
# cut=0,
)
axs[0].set_axisbelow(True)
axs[0].set_xlim(min_, max_)
axs[0].grid(b=True, which="minor", color="#eeeeee90", lw=0.5)
axs[0].grid(b=True, which="major", color="#cccccc20", lw=0.8)
# omit ax[1]
axs[2].set_axisbelow(True)
axs[2].set_xlim(min_, max_)
axs[2].grid(b=True, which="minor", color="#eeeeee90", lw=0.5)
axs[2].grid(b=True, which="major", color="#cccccc20", lw=0.8)
哪个输出:
推荐阅读
- c# - 在c#中检测文本框中的换行符
- ios - 在 MultipeerConnectivity 中扫描时看不到附近的设备
- javascript - 如何将对象数组和嵌套数组分解为具有单个数据的分隔数组
- python - 如何发送与群组 STEAM 相关的发帖请求?
- c# - C# HttpClient 通过 VPN 引发 System.OutOfMemoryException
- anaconda - 自己编译安装ipopt后出现“ApplicationError: Solver (ipopt)没有正常退出”
- python-3.x - 让用户使用字符串创建自定义格式
- c# - 避免 if 和 switch 语句以及更通用的方法
- python - 如何用逗号分割数据,期望双引号中的数据
- node.js - 如何使用节点从 JKS 文件中获取到期日期