如何更改框图中的X轴标签?

发布于 2025-01-17 11:07:56 字数 1581 浏览 3 评论 0原文

我想要一张像这样的图片(只关注箱线图): 在此处输入图像描述 正如您所看到的,图片的 x 标签代表箱线图的平均间距。 我正在尝试使用 seaborn、matplotlib、pd.boxplot 制作类似的东西,但我无法得到它。 我使用的代码是这样的

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
%matplotlib inline

x=np.array([  0.  ,  43.9 ,   0.  ,  21.43,   0.  ,  46.3 ,   0.  ,   0.  ,
        12.2 ,   0.  ,  54.88,  55.56,  53.44,  55.46,   0.  ,  95.58,
        91.03,  40.63,  65.22, 100.  ,  12.95,  97.89,  86.67, 100.  ,
        96.03,  94.12,  97.93, 100.  ,  95.8 ])
y=np.array([ 19.23,  54.29,  29.23,  23.33, 150.  ,  63.53,  35.  ,  12.5 ,
       117.14,  66.67, 273.33, 180.  , 163.75,  56.67, 230.  , 141.25,
       207.14, 118.75, 690.  ,  60.  ,  69.5 , 710.  ,  83.33, 760.  ,
       503.33, 218.57, 290.  , 158.33, 238.33])
z=np.array([ 82.66,  82.66,  82.66,  82.66,  82.66,  82.66, 120.  , 120.  ,
       120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 150.76,
       150.76, 150.76, 150.76, 150.76, 150.76, 150.76, 400.93, 400.93,
       400.93, 400.93, 400.93, 400.93, 400.93])
df=pd.DataFrame({'RQD (%)':x,
                'Spacing (mm)':y,
                'Avarage Spacing':z
                })
sns.boxplot(x='Avarage Spacing',y='RQD (%)',data=df,fliersize=False)

上面几行的结果图片是这样的:

在此处输入图像描述

如果您仔细查看最后一张图片你会意识到它的 x 标签不代表它们自己,因为它们代表 1, 2, 3 y 4。我这样说是因为如果 x 标签代表它们自己,那么箱线图会更加分离,

这样我想要你帮助我这个问题。我希望最后一张图片中的 x 标签能够像第一张图片中那样在 x 轴上表示自己。我想实现这一点,因为我想绘制另一个函数来获得与第一张图片类似的东西。

I want to get a picture like this (just focus on the boxplots):
enter image description here
As you can see the x-labels of the picture represent the average spacing of the boxplot.
I'm trying to make something similar using seaborn, matplotlib, pd.boxplot but I couldn't get it.
The code I used is this

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
%matplotlib inline

x=np.array([  0.  ,  43.9 ,   0.  ,  21.43,   0.  ,  46.3 ,   0.  ,   0.  ,
        12.2 ,   0.  ,  54.88,  55.56,  53.44,  55.46,   0.  ,  95.58,
        91.03,  40.63,  65.22, 100.  ,  12.95,  97.89,  86.67, 100.  ,
        96.03,  94.12,  97.93, 100.  ,  95.8 ])
y=np.array([ 19.23,  54.29,  29.23,  23.33, 150.  ,  63.53,  35.  ,  12.5 ,
       117.14,  66.67, 273.33, 180.  , 163.75,  56.67, 230.  , 141.25,
       207.14, 118.75, 690.  ,  60.  ,  69.5 , 710.  ,  83.33, 760.  ,
       503.33, 218.57, 290.  , 158.33, 238.33])
z=np.array([ 82.66,  82.66,  82.66,  82.66,  82.66,  82.66, 120.  , 120.  ,
       120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 150.76,
       150.76, 150.76, 150.76, 150.76, 150.76, 150.76, 400.93, 400.93,
       400.93, 400.93, 400.93, 400.93, 400.93])
df=pd.DataFrame({'RQD (%)':x,
                'Spacing (mm)':y,
                'Avarage Spacing':z
                })
sns.boxplot(x='Avarage Spacing',y='RQD (%)',data=df,fliersize=False)

The resulting picture of the lines above is this:

enter image description here

If you look carefully at the last picture you will realize that its x-labels don't represent themselves because they represent 1, 2, 3 y 4. I say this because if x-labels would represent themself so the boxplots would be more separated

In that way I want you to help me in this problem. I want x-labels in the last picture to represent themselves in the x-axis like in the first picture. I want to achieve that because I want to draw another function to get something similar to the first picture.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

青萝楚歌 2025-01-24 11:07:57

对于seaborn,这实际上是不可能的,但您可以在下面找到解决方法。
另请参阅此处的更多详细信息: Matplotlib boxplot x axis

对于 Matplotlib 使用 positions (另见下文),对于对数刻度,请参阅评论中@JohanC 发布的链接(Matplotlib 箱线图宽度(以对数比例表示))。

对于 matplotlib,您需要稍微重组数据,我将其包含在下面的代码示例中。

from matplotlib import pyplot as plt
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
%matplotlib inline

x=np.array([  0.  ,  43.9 ,   0.  ,  21.43,   0.  ,  46.3 ,   0.  ,   0.  ,
        12.2 ,   0.  ,  54.88,  55.56,  53.44,  55.46,   0.  ,  95.58,
        91.03,  40.63,  65.22, 100.  ,  12.95,  97.89,  86.67, 100.  ,
        96.03,  94.12,  97.93, 100.  ,  95.8 ])
y=np.array([ 19.23,  54.29,  29.23,  23.33, 150.  ,  63.53,  35.  ,  12.5 ,
       117.14,  66.67, 273.33, 180.  , 163.75,  56.67, 230.  , 141.25,
       207.14, 118.75, 690.  ,  60.  ,  69.5 , 710.  ,  83.33, 760.  ,
       503.33, 218.57, 290.  , 158.33, 238.33])
z=np.array([ 82.66,  82.66,  82.66,  82.66,  82.66,  82.66, 120.  , 120.  ,
       120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 150.76,
       150.76, 150.76, 150.76, 150.76, 150.76, 150.76, 400.93, 400.93,
       400.93, 400.93, 400.93, 400.93, 400.93])
df=pd.DataFrame({'RQD (%)':x,
                'Spacing (mm)':y,
                'Avarage Spacing':z
                })


# reorganize data so they fit into the matplotlib way 
data = df.groupby('Avarage Spacing').agg({'RQD (%)':lambda x: list(x)}).transpose().values[0]

# use positions for the x position
# adjust width to match the size of boxplots to your preferences
plt.boxplot(data,
            positions=df['Avarage Spacing'].unique(),
            widths=20)
plt.show()


# in seaborn its a bit more difficult as x positons are not supported
# you could convert the categories to int and then add a tick for each step
# your categories are then plotted at the right positions as all the other
# categories are empty and plotted as blank spaces 
df['Avarage Spacing'] = df['Avarage Spacing'].astype(int)
sns.boxplot(x='Avarage Spacing',y='RQD (%)',data=df,
            fliersize=False,
            order=range(df['Avarage Spacing'].min()-10,df['Avarage Spacing'].max()+10))
plt.show()

For seaborn it is not really possible but you can find a workaround below.
See also more details here: Matplotlib boxplot x axis

For Matplotlib use positions (see also below) and for log scale see the link posted by @JohanC in the comments (Matplotlib boxplot width in log scale).

For matplotlib you need to restructure the data a bit which I included in the code example below.

from matplotlib import pyplot as plt
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
%matplotlib inline

x=np.array([  0.  ,  43.9 ,   0.  ,  21.43,   0.  ,  46.3 ,   0.  ,   0.  ,
        12.2 ,   0.  ,  54.88,  55.56,  53.44,  55.46,   0.  ,  95.58,
        91.03,  40.63,  65.22, 100.  ,  12.95,  97.89,  86.67, 100.  ,
        96.03,  94.12,  97.93, 100.  ,  95.8 ])
y=np.array([ 19.23,  54.29,  29.23,  23.33, 150.  ,  63.53,  35.  ,  12.5 ,
       117.14,  66.67, 273.33, 180.  , 163.75,  56.67, 230.  , 141.25,
       207.14, 118.75, 690.  ,  60.  ,  69.5 , 710.  ,  83.33, 760.  ,
       503.33, 218.57, 290.  , 158.33, 238.33])
z=np.array([ 82.66,  82.66,  82.66,  82.66,  82.66,  82.66, 120.  , 120.  ,
       120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 120.  , 150.76,
       150.76, 150.76, 150.76, 150.76, 150.76, 150.76, 400.93, 400.93,
       400.93, 400.93, 400.93, 400.93, 400.93])
df=pd.DataFrame({'RQD (%)':x,
                'Spacing (mm)':y,
                'Avarage Spacing':z
                })


# reorganize data so they fit into the matplotlib way 
data = df.groupby('Avarage Spacing').agg({'RQD (%)':lambda x: list(x)}).transpose().values[0]

# use positions for the x position
# adjust width to match the size of boxplots to your preferences
plt.boxplot(data,
            positions=df['Avarage Spacing'].unique(),
            widths=20)
plt.show()


# in seaborn its a bit more difficult as x positons are not supported
# you could convert the categories to int and then add a tick for each step
# your categories are then plotted at the right positions as all the other
# categories are empty and plotted as blank spaces 
df['Avarage Spacing'] = df['Avarage Spacing'].astype(int)
sns.boxplot(x='Avarage Spacing',y='RQD (%)',data=df,
            fliersize=False,
            order=range(df['Avarage Spacing'].min()-10,df['Avarage Spacing'].max()+10))
plt.show()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文