Python maxplotlib - boxsplot 子图 + 散点图

Python maxplotlib - boxsplot subplot + scatter plot

我正在尝试在箱线图中绘制散点图作为子图。当我只为一个箱形图做时,它就起作用了。我可以在箱形图内定义一个具有特定颜色的特定点。绿球(图 1)代表与箱线图值比较的特定数字。

  for columnName in data_num.columns:
    plt.figure(figsize=(2, 2), dpi=100)
    bp = data_num.boxplot(column=columnName, grid=False)
    y = S[columnName]
    x = columnName
    if y > data_num[columnName].describe().iloc[5]:
      plt.plot(1, y, 'r.', alpha=0.7,color='green',markersize=12)
      count_G = count_G + 1
    elif y < data_num[columnName].describe().iloc[5]:
      plt.plot(1, y, 'r.', alpha=0.7,color='red',markersize=12)
      count_L = count_L + 1
    else:
      plt.plot(1, y, 'r.', alpha=0.7,color='yellow',markersize=12)
      count_E = count_E + 1

图片 1 - 散点图 + 1 箱线图

我可以用箱形图创建子图。

  fig, axes = plt.subplots(6,10,figsize=(16,16)) # create figure and axes
  fig.subplots_adjust(hspace=0.6, wspace=1)

  for j,columnName in enumerate(list(data_num.columns.values)[:-1]):
    bp = data_num.boxplot(columnName,ax=axes.flatten()[j])

图 2 - 子图 + 箱线图
但是当我尝试在每个箱线图中绘制一个特定的数字时,实际上它订阅了整个图。

plt.subplot(6,10,j+1)  
if y > data_num[columnName].describe().iloc[5]:
  plt.plot(1, y, 'r.', alpha=0.7,color='green',markersize=12)
  count_G = count_G + 1
elif y < data_num[columnName].describe().iloc[5]:
  plt.plot(1, y, 'r.', alpha=0.7,color='red',markersize=12)
  count_L = count_L + 1
else:
  plt.plot(1, y, 'r.', alpha=0.7,color='black',markersize=12)
  count_E = count_E + 1

图 3 - 子图 + 散点图

目前还不完全清楚哪里出了问题。可能对 plt.subplot(6,10,j+1) 的调用正在删除一些东西。然而,对于 matplotlib 的标准现代使用来说,这样的调用是不必要的,其中子图是通过 fig, axes = plt.subplots() 创建的。注意使用 ax.plot() 而不是 plt.plot()plt.plot() 在“当前”坐标轴上绘制,当有很多子图时可能会有点混乱。

下面的示例代码首先创建了一些玩具数据(希望与问题中的数据相似)。然后在循环中绘制箱线图和各个点。为了避免重复,计数和颜色存储在字典中。由于 data_num[columnName].describe().iloc[5] 似乎是中位数,为了便于阅读,代码直接计算该中位数。

from matplotlib import pyplot as plt
import pandas as pd
import numpy as np

column_names = list('abcdef')
S = {c: np.random.randint(2, 6) for c in column_names}
data_num = pd.DataFrame({c: np.random.randint(np.random.randint(0, 3), np.random.randint(4, 8), 20)
                         for c in column_names})
colors = {'G': 'limegreen', 'E': 'gold', 'L': 'crimson'}
counts = {c: 0 for c in colors}

fig, axes = plt.subplots(1, 6, figsize=(12, 3), gridspec_kw={'hspace': 0.6, 'wspace': 1})
for columnName, ax in zip(data_num.columns, axes.flatten()):
    data_num.boxplot(column=columnName, grid=False, ax=ax)
    y = S[columnName]  # in case S would be a dataframe with one row: y = S[columnName].values[0]
    data_median = data_num[columnName].median()
    classification = 'G' if y > data_median else 'L' if y < data_median else 'E'
    ax.plot(1, y, '.', alpha=0.9, color=colors[classification], markersize=12)
    counts[classification] += 1
print(counts)
plt.show()