绘制象限图以根据 X 和 Y 的平均值区分 4 组中的人口并找到最终计数
Posted
技术标签:
【中文标题】绘制象限图以根据 X 和 Y 的平均值区分 4 组中的人口并找到最终计数【英文标题】:Plotting quadrant chart to differntiate population in 4 groups based on mean values of X & Y and find the final count 【发布时间】:2021-10-14 08:32:01 【问题描述】:开始学习如何在 python 上绘制数据,我需要帮助实现以下目标:
我有下面的例子df6:
df6 = pd.DataFrame(
'emails': [50, 60 ,30, 40, 90, 10, 0,85 ],
'delivered': [20, 16 ,6, 15, 66, 6, 0,55 ]
)
df6
看起来像:
emails delivered
0 50 20
1 60 16
2 30 6
3 40 15
4 90 66
5 10 6
6 0 0
7 85 55
我需要在 4 象限图表中绘制 emails
VS delivered
。 X 和 Y 范围将稍微超出最大值,横截面将是两列的平均值。
到目前为止我所做的,使用describe()
获取 df6 的值然后:
fig, ax = plt.subplots()
fig.set_size_inches(7, 5)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.axhline(y=45.6, color="black", linestyle="--")
plt.axvline(x=23, color="black", linestyle="--")
plt.plot(df6['delivered'],df6['emails'],"o")
plt.xlim([0, df6['delivered'].max()+20])
plt.ylim([0, df6['emails'].max()+20])
plt.show()
到目前为止,我得到了以下输出:
我正在寻找的是将图表分成分散的 4 个组,并用四分之一的总数标记每个组:
【问题讨论】:
【参考方案1】:您只是缺少设置左/下脊椎位置的代码
import pandas as pd, numpy as np
df6 = pd.DataFrame('emails': [50, 60 ,30, 40, 90, 10, 0,85 ],
'delivered': [20, 16 ,6, 15, 66, 6, 0,55 ])
plt.plot(df6['delivered'],df6['emails'],"o")
count = np.count_nonzero(
(df6['emails'] < df6['delivered'].mean())&
(df6['delivered'] < df6['emails'].mean()) )
plt.annotate('count: %s'%count,(5,60))
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['left'].set_position(('data',df6['delivered'].mean()))
plt.gca().spines['bottom'].set_position(('data',df6['emails'].mean()))
【讨论】:
【参考方案2】:因此,要在绘图中使用这些方法,您可以从简单地修改以下 2 行开始:
plt.axhline(y=df6['emails'].mean(), color="black", linestyle="--")
plt.axvline(x=df6['delivered'].mean(), color="black", linestyle="--")
然后我们可以使用pd.value_counts
来计算计数:
counts = df6.transform(lambda s: s >= s.mean()).value_counts()
pos = df6.agg(['min', 'max'])
这里counts
包含每对上/下均值的值:
emails delivered
False False 4
True False 2
True 2
而pos
包含放置盒子的 x/y(或电子邮件/已发送)坐标:
emails delivered
min 0 0
max 90 66
所以你可以调整pos
来改变注解的位置。
最后要在图上做标注:
for (eml, dlv), num in counts.iteritems():
ax.text(s=f'count: num',
x=pos.loc['max' if dlv else 'min', 'delivered'],
y=pos.loc['max' if eml else 'min', 'emails'],
ha='right' if dlv else 'left',
va='top' if eml else 'bottom',
)
【讨论】:
【参考方案3】:这是另一种解决方案,具有更对称的图:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame(
"emails": [50, 60, 30, 40, 90, 10, 0, 85],
"delivered": [20, 16, 6, 15, 66, 6, 0, 55],
)
plt.plot(df["delivered"], df["emails"], "o")
plt.gca().spines["top"].set_visible(False)
plt.gca().spines["right"].set_visible(False)
plt.gca().spines["left"].set_position(("data", df["delivered"].mean()))
plt.gca().spines["bottom"].set_position(("data", df["emails"].mean()))
def get_lims(df, column, w=0.1):
mean = df[column].mean()
max_diff = max(
abs(df[column].max() - mean),
abs(df[column].min() - mean),
)
return [mean - max_diff - max_diff * w, mean + max_diff + max_diff * w]
plt.xlim(get_lims(df, "delivered"))
plt.ylim(get_lims(df, "emails"))
plt.show()
【讨论】:
【参考方案4】:我发现在绘图之前对数据进行规范化更容易......更新:搞砸了计数,但代码在这里分析我的错误。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scale = scaler.fit(df6)
# normalize the sen_matrix
norm_df = pd.DataFrame(scale.transform(df6), columns=df6.columns)
quadrant_1 = sum(np.logical_and(norm_df['emails'] < 0, norm_df['delivered'] < 0))
display(quadrant_1)
quadrant_2 = sum(np.logical_and(norm_df['emails'] > 0, norm_df['delivered'] < 0))
display(quadrant_2)
quadrant_3 = sum(np.logical_and(norm_df['emails'] < 0, norm_df['delivered'] > 0))
display(quadrant_3)
quadrant_4 = sum(np.logical_and(norm_df['emails'] > 0, norm_df['delivered'] > 0))
display(quadrant_4)
fig, ax = plt.subplots()
fig.set_size_inches(7, 5)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.axhline(y=0, color="black", linestyle="--")
plt.axvline(x=0, color="black", linestyle="--")
plt.plot(norm_df['delivered'],norm_df['emails'],"o")
plt.gca().spines['bottom'].set_visible(False)
plt.gca().spines['left'].set_visible(False)
plt.gca().axes.get_xaxis().set_visible(False)
plt.gca().axes.get_yaxis().set_visible(False)
plt.text(0,-2.1,'Delivered',horizontalalignment='center', verticalalignment='center')
plt.text(-2.1,0,'Emails', horizontalalignment='center', verticalalignment='center', rotation=90)
plt.text(1,1,'Count: ' + str(quadrant_1),horizontalalignment='center', verticalalignment='center')
plt.text(-1,1,'Count: ' + str(quadrant_2), horizontalalignment='center', verticalalignment='center')
plt.text(-1,-1,'Count: ' + str(quadrant_3),horizontalalignment='center', verticalalignment='center')
plt.text(1,-1,'Count: ' + str(quadrant_4), horizontalalignment='center', verticalalignment='center')
plt.xlim([-2, 2])
plt.ylim([-2, 2])
plt.show()
【讨论】:
以上是关于绘制象限图以根据 X 和 Y 的平均值区分 4 组中的人口并找到最终计数的主要内容,如果未能解决你的问题,请参考以下文章
c语言编程问题:输入4个任意数字,然后按从小到大的顺序输入坐标点(x,y),输出该点所在的象限。代码是: