matplotlib boxplot 与覆盖的散点图不对齐
matplotlib boxplot doesn't align with overlaid scatterplot
我有一个图,我试图在箱线图系列上叠加一个散点系列...这是一个简单的问题示例,以便您可以重新创建它。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
names = ['a','b','c','d','e','f']
df = pd.DataFrame(np.random.rand(6,6), columns=names)
display(df)
plt.boxplot(df, labels=names)
plt.show()
plt.scatter(names, df.head(1))
plt.show()
plt.boxplot(df, labels=names)
plt.scatter(names, df.head(1))
plt.show()
结果:
所以您会看到,当箱线图和散点图都添加到同一个图中时,标签不再正确对齐。我该如何解决这个对齐问题?
传递给散点图的数据形状不正确,需要移动索引,因为箱线图索引从 1 开始。
这是一个可行的解决方案:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
names = ['a','b','c','d','e','f']
df = pd.DataFrame(np.random.rand(6,6), columns=names)
display(df)
plt.boxplot(df, labels=names)
plt.show()
df2 = df.copy()
df2.columns = range(1, len(df2.columns)+1)
df2 = df2.unstack().reset_index(level=0)
plt.scatter(*df2.values.T)
plt.show()
plt.boxplot(df, labels=names)
plt.scatter(*df2.values.T)
plt.show()
需要喂什么给scatter
:
[1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3.,
3., 4., 4., 4., 4., 4., 4., 5., 5., 5., 5., 5., 5., 6., 6., 6., 6.,
6., 6.]
和
[0.40196123, 0.24802927, 0.3152357 , 0.76739054, 0.06847434,
0.30173798, 0.30350823, 0.36324843, 0.35928768, 0.69194326,
0.61586685, 0.74039024, 0.56971769, 0.37970524, 0.67049866,
0.82031296, 0.15917911, 0.58760412, 0.02660848, 0.67014213,
0.46027398, 0.39161172, 0.01191327, 0.48197714, 0.79882359,
0.84189102, 0.10873758, 0.56858526, 0.48169526, 0.08860958,
0.43500853, 0.26380151, 0.14911615, 0.47846386, 0.25583401,
0.04949216]
- 在
python 3.8.11
、pandas 1.3.2
、matplotlib 3.4.3
、seaborn 0.11.2
中测试
- 请注意
xticklabel
个位置未对齐。
- 根据
matplotlib.pyplot.boxplot
,position
默认为range(1, N+1)
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 8))
ax1.boxplot(df, labels=names)
print(ax1.get_xticks())
ax2.scatter(names, df.head(1))
print(ax2.get_xticks())
ax3.boxplot(df, labels=names)
ax3.scatter(names, df.head(1))
[out]:
[1 2 3 4 5 6]
[0, 1, 2, 3, 4, 5]
- 根据现有代码,正确的解决方案是设置
positions
参数
- 对于散点图,这还需要使用
pandas.DataFrame.melt
将数据帧转换为长格式。
plt.boxplot(df, labels=names, positions=range(len(df.columns)))
plt.scatter(data=df.melt(), x='variable', y='value')
- 或者,直接用
pandas.DataFrame.plot
绘图
ax = df.plot(kind='box', positions=range(len(df.columns)))
df.melt().plot(kind='scatter', x='variable', y='value', ax=ax)
- 最简单的解决方案是使用
seaborn
,这是matplotlib
的高级API。这直接绘制给定的数据框,没有任何转换
seaborn.boxplot
and seaborn.swarmplot
, which is a better option than seaborn.scatterplot
.boxplot
个位置从 0 开始
import seaborn as sns
sns.boxplot(data=df, boxprops={'facecolor':'None'})
print(plt.xticks())
sns.swarmplot(data=df)
print(plt.xticks())
[out]:
(array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])
(array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])
我有一个图,我试图在箱线图系列上叠加一个散点系列...这是一个简单的问题示例,以便您可以重新创建它。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
names = ['a','b','c','d','e','f']
df = pd.DataFrame(np.random.rand(6,6), columns=names)
display(df)
plt.boxplot(df, labels=names)
plt.show()
plt.scatter(names, df.head(1))
plt.show()
plt.boxplot(df, labels=names)
plt.scatter(names, df.head(1))
plt.show()
结果:
所以您会看到,当箱线图和散点图都添加到同一个图中时,标签不再正确对齐。我该如何解决这个对齐问题?
传递给散点图的数据形状不正确,需要移动索引,因为箱线图索引从 1 开始。
这是一个可行的解决方案:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
names = ['a','b','c','d','e','f']
df = pd.DataFrame(np.random.rand(6,6), columns=names)
display(df)
plt.boxplot(df, labels=names)
plt.show()
df2 = df.copy()
df2.columns = range(1, len(df2.columns)+1)
df2 = df2.unstack().reset_index(level=0)
plt.scatter(*df2.values.T)
plt.show()
plt.boxplot(df, labels=names)
plt.scatter(*df2.values.T)
plt.show()
需要喂什么给scatter
:
[1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3.,
3., 4., 4., 4., 4., 4., 4., 5., 5., 5., 5., 5., 5., 6., 6., 6., 6.,
6., 6.]
和
[0.40196123, 0.24802927, 0.3152357 , 0.76739054, 0.06847434,
0.30173798, 0.30350823, 0.36324843, 0.35928768, 0.69194326,
0.61586685, 0.74039024, 0.56971769, 0.37970524, 0.67049866,
0.82031296, 0.15917911, 0.58760412, 0.02660848, 0.67014213,
0.46027398, 0.39161172, 0.01191327, 0.48197714, 0.79882359,
0.84189102, 0.10873758, 0.56858526, 0.48169526, 0.08860958,
0.43500853, 0.26380151, 0.14911615, 0.47846386, 0.25583401,
0.04949216]
- 在
python 3.8.11
、pandas 1.3.2
、matplotlib 3.4.3
、seaborn 0.11.2
中测试
- 请注意
xticklabel
个位置未对齐。 - 根据
matplotlib.pyplot.boxplot
,position
默认为range(1, N+1)
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 8))
ax1.boxplot(df, labels=names)
print(ax1.get_xticks())
ax2.scatter(names, df.head(1))
print(ax2.get_xticks())
ax3.boxplot(df, labels=names)
ax3.scatter(names, df.head(1))
[out]:
[1 2 3 4 5 6]
[0, 1, 2, 3, 4, 5]
- 根据现有代码,正确的解决方案是设置
positions
参数 - 对于散点图,这还需要使用
pandas.DataFrame.melt
将数据帧转换为长格式。
plt.boxplot(df, labels=names, positions=range(len(df.columns)))
plt.scatter(data=df.melt(), x='variable', y='value')
- 或者,直接用
pandas.DataFrame.plot
绘图
ax = df.plot(kind='box', positions=range(len(df.columns)))
df.melt().plot(kind='scatter', x='variable', y='value', ax=ax)
- 最简单的解决方案是使用
seaborn
,这是matplotlib
的高级API。这直接绘制给定的数据框,没有任何转换seaborn.boxplot
andseaborn.swarmplot
, which is a better option thanseaborn.scatterplot
.boxplot
个位置从 0 开始
import seaborn as sns
sns.boxplot(data=df, boxprops={'facecolor':'None'})
print(plt.xticks())
sns.swarmplot(data=df)
print(plt.xticks())
[out]:
(array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])
(array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])