Tar*_*a S 4 python matplotlib pandas
我有一个简单的 pandas 数据框,我想用 matplotlib 绘制它:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_excel('SAT_data.xlsx', index_col = 'State')
plt.figure()
plt.scatter(df['Year'], df['Reading'], c = 'blue', s = 25)
plt.scatter(df['Year'], df['Math'], c = 'orange', s = 25)
plt.scatter(df['Year'], df['Writing'], c = 'red', s = 25)
Run Code Online (Sandbox Code Playgroud)
这是我的情节:

我想将蓝色数据点向左移动一点,将红色数据点向右移动一点,因此每年 x 轴上都有三个迷你散点数据列,而不是所有三个数据集都重叠。我尝试并未能正确使用“verts”参数。有一个更好的方法吗?
使用偏移变换将允许以点为单位而不是数据单位将散点移动一定量。优点是它们总是相互紧靠,与图形大小、缩放级别等无关。
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(0)
import matplotlib.transforms as transforms
year = np.random.choice(np.arange(2006,2017), size=(300) )
values = np.random.rand(300, 3)
plt.figure()
offset = lambda p: transforms.ScaledTranslation(p/72.,0, plt.gcf().dpi_scale_trans)
trans = plt.gca().transData
sc1 = plt.scatter(year, values[:,0], c = 'blue', s = 25, transform=trans+offset(-5))
plt.scatter(year, values[:,1], c = 'orange', s = 25)
plt.scatter(year, values[:,2], c = 'red', s = 25, transform=trans+offset(5))
plt.show()
Run Code Online (Sandbox Code Playgroud)
一些解释:
问题是我们想要向数据坐标中的某些数据添加以点为单位的偏移量。虽然数据坐标会自动转换为使用transData(我们通常在表面上看不到)显示坐标,但添加一些偏移量需要我们更改转换。
我们通过添加偏移量来做到这一点。虽然我们可以只添加以像素(显示坐标)为单位的偏移量,但添加以点为单位的偏移量会更方便,从而使用与中给出的散点大小相同的单位(它们的大小实际上是点的平方)。那么我们想知道点有多少像素p?通过除以pppi(每英寸点数)得到英寸,然后乘以 dpi(每英寸点数)得到显示像素。此计算在 ScaledTranslation 中完成。虽然每英寸点数原则上是可变的(并由变换处理dpi_scale_trans),但每英寸点数是固定的。Matplotlib 使用 72 ppi,这是一种排版标准。
一种快速而肮脏的方法是创建一个小的偏移量dx,然后从蓝点的值中减去它x,然后添加到x红点的值中。
dx = 0.1
plt.scatter(df['Year'] - dx, df['Reading'], c = 'blue', s = 25)
plt.scatter(df['Year'], df['Math'], c = 'orange', s = 25)
plt.scatter(df['Year'] + dx, df['Writing'], c = 'red', s = 25)
Run Code Online (Sandbox Code Playgroud)
另一种选择可能是使用库中的stripplot函数seaborn。有必要将原始数据框融合为长格式,以便每一行包含一年、一项测试和一个分数。然后指定stripplot年份为x,得分为y,测试为hue。关键字split参数控制将类别绘制为每个类别的单独条纹x。还有一种jitter观点认为,会给x值添加一些噪音,以便它们占据一些小区域,而不是在一条垂直线上。
import pandas as pd
import seaborn as sns
# make up example data
np.random.seed(2017)
df = pd.DataFrame(columns = ['Reading','Math','Writing'],
data = np.random.normal(540,30,size=(1000,3)))
df['Year'] = np.random.choice(np.arange(2006,2016),size=1000)
# melt the data into long form
df1 = pd.melt(df, var_name='Test', value_name='Score',id_vars=['Year'])
# make a stripplot
fig, ax = plt.subplots(figsize=(10,7))
sns.stripplot(data = df1, x='Year', y = 'Score', hue = 'Test',
jitter = True, split = True, alpha = 0.7,
palette = ['blue','orange','red'])
Run Code Online (Sandbox Code Playgroud)
输出: