在 twinx 上的 seaborn 中将 x 轴数值与相应的分类变量对齐
Aligning x axis numerical values with corresponding categorical variables in seaborn on twinx
我正在尝试绘制双 x 轴 seaborn 线图,但基于以下代码的输出显示两个 x 轴都卡在角落而不是将值彼此对齐。
我错过了什么?
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
plt.style.use("fivethirtyeight")
fig, ax = plt.subplots(1,1,figsize=(10,10))
ax2 = ax.twinx()
sns.lineplot(x="BUCKET_SEGMENT_1", y= 'Percentage to Bucket Total', data=df, ax=ax)
sns.lineplot(x="PAST_DUE_DAYS", y= 'Percentage to Bucket Total',data=df, ax=ax2)
plt.show()
数据
BUCKET_SEGMENT_1 PAST_DUE_DAYS BAL Percentage to Bucket Total
0 Bucket1 3.0 878698.045 74.431434
1 Bucket1 4.0 25747.397 2.180971
2 Bucket2 6.0 171683.523 14.54271
3 Bucket2 7.0 55659.448 4.714716
4 Bucket3 8.0 1589.759 0.134662
这是我希望看到的示例
我也尝试过使用 ax 和 ax2 设置限制和 xticks 但没能成功
DF = df.copy()
DF.set_index("BUCKET_SEGMENT_1",inplace=True)
fig, ax = plt.subplots(1,1,figsize=(10,10))
ax2 = ax.twinx()
sns.lineplot(data=DF,x="PAST_DUE_DAYS",y='Percentage to Bucket Total',ax=ax)
sns.lineplot(data=DF.reset_index(),x='BUCKET_SEGMENT_1',y='Percentage to Bucket Total',ax=ax2)
x = int(max(DF.PAST_DUE_DAYS))
ax.set_xlim(0,x)
ax2.set_xticks(DF.index.unique())
要找出发生了什么,首先将两个图绘制在单独的子图中会有所帮助:
import matplotlib.pyplot as plt
import pandas as pd
from io import StringIO
df_str = '''BUCKET_SEGMENT_1 PAST_DUE_DAYS BAL "Percentage to Bucket Total"
0 Bucket1 3.0 878698.045 74.431434
1 Bucket1 4.0 25747.397 2.180971
2 Bucket2 6.0 171683.523 14.54271
3 Bucket2 7.0 55659.448 4.714716
4 Bucket3 8.0 1589.759 0.134662'''
df = pd.read_csv(StringIO(df_str), delim_whitespace=True)
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(14, 5))
sns.lineplot(x="BUCKET_SEGMENT_1", y='Percentage to Bucket Total', data=df, ax=ax1)
sns.lineplot(x="PAST_DUE_DAYS", y='Percentage to Bucket Total', data=df, ax=ax2)
ax2.set_xticks(df["PAST_DUE_DAYS"])
plt.tight_layout()
plt.show()
左侧子图使用 x 轴的分类桶名称。所有百分比均取平均值,并显示误差带。 Bucket1
、Bucket2
和 Bucket3
,位于内部位置 0
、1
和 2
。
右边的子图使用数字 PAST_DUE_DAYS
位置作为 x 轴。每天只有一个百分比值,所以不需要误差带。
ax.twinx()
将共享 x 轴。这会将第一个子图位置 (0,1,2) 与第二个子图的数字位置 (3,4,6,7,8) 混合。结果是您看到的奇怪情节(显然来自不同的数据框作为示例)。
现在,要将桶标记到数值图中,您可以使用 groupby()
找出位置。使用最小和最大天数,可以定位文本。此外,交替的彩色条带可以使范围可视化。
下面是一些帮助您入门的示例代码:
fig, ax = plt.subplots(figsize=(10, 5))
sns.lineplot(x="PAST_DUE_DAYS", y='Percentage to Bucket Total', data=df, ax=ax)
colors = ['red', 'green']
previous_max_days = 0
for (group_name, group_data), color in zip(df.groupby("BUCKET_SEGMENT_1"), colors * len(df)):
# min_days = group_data['PAST_DUE_DAYS'].min() - 0.5
min_days = previous_max_days
max_days = group_data['PAST_DUE_DAYS'].max() + 0.5
ax.axvspan(min_days, max_days, color=color, alpha=0.1)
ax.text((min_days + max_days) / 2, 0.9, group_name, ha='center', fontsize=20, color=color,
transform=ax.get_xaxis_transform())
previous_max_days = max_days
plt.show()
我正在尝试绘制双 x 轴 seaborn 线图,但基于以下代码的输出显示两个 x 轴都卡在角落而不是将值彼此对齐。
我错过了什么?
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
plt.style.use("fivethirtyeight")
fig, ax = plt.subplots(1,1,figsize=(10,10))
ax2 = ax.twinx()
sns.lineplot(x="BUCKET_SEGMENT_1", y= 'Percentage to Bucket Total', data=df, ax=ax)
sns.lineplot(x="PAST_DUE_DAYS", y= 'Percentage to Bucket Total',data=df, ax=ax2)
plt.show()
数据
BUCKET_SEGMENT_1 PAST_DUE_DAYS BAL Percentage to Bucket Total
0 Bucket1 3.0 878698.045 74.431434
1 Bucket1 4.0 25747.397 2.180971
2 Bucket2 6.0 171683.523 14.54271
3 Bucket2 7.0 55659.448 4.714716
4 Bucket3 8.0 1589.759 0.134662
这是我希望看到的示例
我也尝试过使用 ax 和 ax2 设置限制和 xticks 但没能成功
DF = df.copy()
DF.set_index("BUCKET_SEGMENT_1",inplace=True)
fig, ax = plt.subplots(1,1,figsize=(10,10))
ax2 = ax.twinx()
sns.lineplot(data=DF,x="PAST_DUE_DAYS",y='Percentage to Bucket Total',ax=ax)
sns.lineplot(data=DF.reset_index(),x='BUCKET_SEGMENT_1',y='Percentage to Bucket Total',ax=ax2)
x = int(max(DF.PAST_DUE_DAYS))
ax.set_xlim(0,x)
ax2.set_xticks(DF.index.unique())
要找出发生了什么,首先将两个图绘制在单独的子图中会有所帮助:
import matplotlib.pyplot as plt
import pandas as pd
from io import StringIO
df_str = '''BUCKET_SEGMENT_1 PAST_DUE_DAYS BAL "Percentage to Bucket Total"
0 Bucket1 3.0 878698.045 74.431434
1 Bucket1 4.0 25747.397 2.180971
2 Bucket2 6.0 171683.523 14.54271
3 Bucket2 7.0 55659.448 4.714716
4 Bucket3 8.0 1589.759 0.134662'''
df = pd.read_csv(StringIO(df_str), delim_whitespace=True)
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(14, 5))
sns.lineplot(x="BUCKET_SEGMENT_1", y='Percentage to Bucket Total', data=df, ax=ax1)
sns.lineplot(x="PAST_DUE_DAYS", y='Percentage to Bucket Total', data=df, ax=ax2)
ax2.set_xticks(df["PAST_DUE_DAYS"])
plt.tight_layout()
plt.show()
左侧子图使用 x 轴的分类桶名称。所有百分比均取平均值,并显示误差带。 Bucket1
、Bucket2
和 Bucket3
,位于内部位置 0
、1
和 2
。
右边的子图使用数字 PAST_DUE_DAYS
位置作为 x 轴。每天只有一个百分比值,所以不需要误差带。
ax.twinx()
将共享 x 轴。这会将第一个子图位置 (0,1,2) 与第二个子图的数字位置 (3,4,6,7,8) 混合。结果是您看到的奇怪情节(显然来自不同的数据框作为示例)。
现在,要将桶标记到数值图中,您可以使用 groupby()
找出位置。使用最小和最大天数,可以定位文本。此外,交替的彩色条带可以使范围可视化。
下面是一些帮助您入门的示例代码:
fig, ax = plt.subplots(figsize=(10, 5))
sns.lineplot(x="PAST_DUE_DAYS", y='Percentage to Bucket Total', data=df, ax=ax)
colors = ['red', 'green']
previous_max_days = 0
for (group_name, group_data), color in zip(df.groupby("BUCKET_SEGMENT_1"), colors * len(df)):
# min_days = group_data['PAST_DUE_DAYS'].min() - 0.5
min_days = previous_max_days
max_days = group_data['PAST_DUE_DAYS'].max() + 0.5
ax.axvspan(min_days, max_days, color=color, alpha=0.1)
ax.text((min_days + max_days) / 2, 0.9, group_name, ha='center', fontsize=20, color=color,
transform=ax.get_xaxis_transform())
previous_max_days = max_days
plt.show()