前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关系(一)利用python绘制散点图

关系(一)利用python绘制散点图

作者头像
HsuHeinrich
发布2024-03-26 16:28:24
650
发布2024-03-26 16:28:24
举报
文章被收录于专栏:HsuHeinrichHsuHeinrich

关系(一)利用python绘制散点图

散点图 (Scatterplot)简介

1

在笛卡尔座标上放置一系列的数据点,检测两个变量之间的关系,这就是散点图。

散点图可以了解数据之间的各种相关性,如正比、反比、无相关、线性、指数级、 U形等,而且也可以通过数据点的密度(辅助拟合趋势线)来确定相关性的强度。另外,也可以探索出异常值(在远超出一般聚集区域的数据点称)。

快速绘制

基于seaborn

代码语言:javascript
复制
import seaborn as sns
import matplotlib.pyplot as plt

# 导入数据
df = sns.load_dataset('iris')

# 基于scatterplot函数绘制散点图
sns.scatterplot(x=df["sepal_length"], y=df["sepal_width"])

plt.show()

2

基于matplotlib

代码语言:javascript
复制
import seaborn as sns
import matplotlib.pyplot as plt

# 导入数据
df = sns.load_dataset('iris')

# 基于plot函数绘制散点图
plt.plot( 'sepal_length', 'sepal_width', data=df, linestyle='none', marker='o')

plt.show()

3

定制多样化的散点图

自定义散点图一般是结合使用场景对相关参数进行修改,并辅以其他的绘图知识。参数信息可以通过官网进行查看,其他的绘图知识则更多来源于实战经验,大家不妨将接下来的绘图作为一种学习经验,以便于日后总结。

通过seaborn绘制多样化的散点图

seaborn主要利用scatterplotregplot绘制散点图,可以通过seaborn.scatterplot[1]seaborn.regplot[2]了解更多用法

修改参数

代码语言:javascript
复制
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

sns.set(font='SimHei', font_scale=0.8, style="darkgrid") # 解决Seaborn中文显示问题

# 导入数据
df = sns.load_dataset("iris")

# 构造子图
fig, ax = plt.subplots(2,2,constrained_layout=True, figsize=(8, 8))

# 增加趋势拟合线
ax_sub = sns.regplot(x=df["sepal_length"], y=df["sepal_width"], fit_reg=True,
                         line_kws={"color":"r","alpha":0.7,"lw":5},ax=ax[0][0])
ax_sub.set_title('增加趋势拟合线')

# 自定义标记类型
ax_sub = sns.regplot(x=df["sepal_length"], y=df["sepal_width"], marker="+", fit_reg=False, ax=ax[0][1])
ax_sub.set_title('自定义标记类型')

# 自定义标记外形
ax_sub = sns.regplot(x=df["sepal_length"], y=df["sepal_width"], fit_reg=False, 
                        scatter_kws={"color":"darkred", # 颜色
                                  "alpha":0.3, # 透明度
                                  "s":200}, # 点大小
                        ax=ax[1][0]
                    )
ax_sub.set_title('自定义标记外形')

# 自定义每个点颜色
value=(df['sepal_length']>6) & (df['sepal_width']>3) # 构造特殊的点
df['color']= np.where( value==True , "#9b59b6", "#3498db") # 颜色区分

ax_sub = sns.regplot(data=df, x=df["sepal_length"], y=df["sepal_width"], fit_reg=False,
                scatter_kws={'facecolors':df['color']},ax=ax[1][1])
ax_sub.set_title('自定义每个点颜色')

plt.show()

4

分组散点图

代码语言:javascript
复制
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.gridspec as gridspec

# 导入自定义模块
import SeabornFig2Grid as sfg

sns.set(font='SimHei', font_scale=0.8, style="darkgrid") # 解决Seaborn中文显示问题

# 导入数据
df = sns.load_dataset('iris')

fig = plt.figure(figsize=(8, 8))
gs = gridspec.GridSpec(2, 2)

# 默认的分组散点图
scatter1 =sns.lmplot( x="sepal_length", y="sepal_width", data=df, fit_reg=False, hue='species', legend=False)
scatter1.ax.set_title('默认的分组散点图')

# 自定义每组的标记
scatter2 = sns.lmplot( x="sepal_length", y="sepal_width", data=df, fit_reg=False, hue='species', legend=False, markers=["o", "x", "1"])
scatter2.ax.set_title('自定义每组的标记')

# 自定义调色板
scatter3 = sns.lmplot( x="sepal_length", y="sepal_width", data=df, fit_reg=False, hue='species', legend=False, palette="Set2")
scatter3.ax.set_title('自定义调色板')

# 自定义颜色
scatter4 = sns.lmplot( x="sepal_length", y="sepal_width", data=df, fit_reg=False, hue='species', legend=False, palette=dict(setosa="#9b59b6", virginica="#3498db", versicolor="#95a5a6"))
scatter4.ax.set_title('自定义颜色')

# 使用SeabornFig2Grid转换 seaborn 图为 matplotlib 子图
mg1 = sfg.SeabornFig2Grid(scatter1, fig, gs[0])
mg2 = sfg.SeabornFig2Grid(scatter2, fig, gs[1])
mg3 = sfg.SeabornFig2Grid(scatter3, fig, gs[2])
mg4 = sfg.SeabornFig2Grid(scatter4, fig, gs[3])

gs.tight_layout(fig)
plt.show()

5

添加文本注释

代码语言:javascript
复制
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns

# 自定义数据
df = pd.DataFrame({
'x': [1, 1.5, 3, 4, 5],
'y': [5, 15, 5, 10, 2],
'group': ['A','other group','B','C','D']
})

# 绘制基本散点图
sns.regplot(data=df, x="x", y="y", fit_reg=False, marker="o", color="skyblue", scatter_kws={'s':400})

# 为每个点添加注释
for line in range(0,df.shape[0]):
     plt.text(df.x[line]+0.2, df.y[line], df.group[line], horizontalalignment='left', size='medium', color='black', weight='semibold')

plt.show()

6

通过matplotlib绘制多样化的散点图

matplotlib主要利用plot绘制散点图,可以通过matplotlib.pyplot.plot[3]了解更多用法

自定义散点图

代码语言:javascript
复制
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np 
import pandas as pd
import palmerpenguins

mpl.rcParams.update(mpl.rcParamsDefault) # 恢复默认的matplotlib样式
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签

# 设置随机种子
np.random.seed(0)

# 自定义数据
df=pd.DataFrame({'x_pos': range(1,101), 'y_pos': np.random.randn(100)*80+range(1,101) })

# 初始化
fig = plt.figure(figsize=(12,8))

# 1、自定义标记
ax = plt.subplot2grid((2, 2), (0, 0), colspan=1)
plt.plot( 'x_pos', 'y_pos', data=df, linestyle='none', marker='*', # 标记形状
                markersize=12, # 标记大小
                markerfacecolor='skyblue', # 标记颜色
                markeredgewidth=0.3, # 标记边缘
                markeredgecolor="orange", # 标记边缘颜色
                 )
ax.set_title('自定义标记')


# 2、添加注释信息
ax = plt.subplot2grid((2, 2), (0, 1), colspan=1)
plt.plot( 'x_pos', 'y_pos', data=df, linestyle='none', marker='o')
# 文本
plt.annotate('有趣的点!', xy=(25, 200), xytext=(0, 300),
                      # 自定义箭头
                     arrowprops=dict(facecolor='black', shrink=0.005))
# 公式
plt.text(70, -120, r'equation: $\sum_{i=0}^\infty x_i$', fontsize=12)
# 正方形边缘框 
# patches.Circle为圆形边框,patches.Ellipse为椭圆形边框
ax.add_patch(
                patches.Rectangle(
                (70, 100), # (x,y)
                25, # 宽
                50, # 高
                alpha=0.3, facecolor="red", edgecolor="black", linewidth=3, linestyle='solid')
        )
# 坐标线(水平与垂直线)
plt.axvline(40, color='r'),plt.axhline(40, color='r')
ax.set_title('添加注释信息')


# 3、自定义图例
# 导入数据
data = palmerpenguins.load_penguins() 
# 数据定义
FLIPPER_LENGTH = data["flipper_length_mm"].values # flipper长度数据
BILL_LENGTH = data["bill_length_mm"].values # bill长度数据
SPECIES = data["species"].values # 物种类别数据
SPECIES_ = np.unique(SPECIES) # 物种唯一值
COLORS = ["#1B9E77", "#D95F02", "#7570B3"] # 颜色列表

ax = plt.subplot2grid((2, 2), (1, 0), colspan=1)
for species, color in zip(SPECIES_, COLORS):
    idxs = np.where(SPECIES == species)
    ax.scatter(
        FLIPPER_LENGTH[idxs], BILL_LENGTH[idxs], label=species,
        s=50, color=color, alpha=0.7
    )
# 位置、大小等图例参数
legend = ax.legend(loc="lower right", fontsize=6, markerscale=2, labelspacing=2, frameon=False)
handles = legend.legendHandles
# 自定义标识
hatches = ["+", "x", "o"]
for i, handle in enumerate(handles):
    handle.set_edgecolor("#6c2167")
    handle.set_facecolor(COLORS[i])
    handle.set_hatch(hatches[i])
    handle.set_alpha(0.7)
ax.set_title('自定义图例')


# 4、回归拟合线
# 自定义数据
rng = np.random.default_rng(1234)
x = rng.uniform(0, 10, size=100)
y = x + rng.normal(size=100)

# 绘制散点图
ax = plt.subplot2grid((2, 2), (1, 1), colspan=1)
ax.scatter(x, y, s=60, alpha=0.7, edgecolors="k")

# 拟合-polyfit返回斜率b和截距a
b, a = np.polyfit(x, y, deg=1)

# 绘制回归线
xseq = np.linspace(0, 10, num=100) # x轴
ax.plot(xseq, a + b * xseq, color="k", lw=2.5)
ax.set_title('回归拟合线')

plt.show()

7

对数刻度线

代码语言:javascript
复制
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np 
import pandas as pd

plt.rcParams['font.sans-serif'] = ['DejaVu Sans'] # 用来正常显示'-' [U+2212]问题

# 自定义数据
rng = np.random.default_rng(1234)
x = rng.lognormal(size=200)
y = x + rng.normal(scale=5 * (x / np.max(x)), size=200)

# 初始化
fig = plt.figure(figsize=(10,6))

# 原始散点图
ax = plt.subplot2grid((2, 2), (0, 0), colspan=1)
ax.scatter(x, y, s=60, alpha=0.7, edgecolors="k")
ax.set_title('default')

# x轴对数刻度
ax = plt.subplot2grid((2, 2), (0, 1), colspan=1)
ax.scatter(x, y, s=60, alpha=0.7, edgecolors="k")
ax.set_xscale("log")
ax.set_title('logarithmic scale for x axes')

# y轴对数刻度
ax = plt.subplot2grid((2, 2), (1, 0), colspan=1)
ax.scatter(x, y, s=60, alpha=0.7, edgecolors="k")
ax.set_yscale("log")
ax.set_title('logarithmic scale for y axes')

# xy轴对数刻度
ax = plt.subplot2grid((2, 2), (1, 1), colspan=1)
ax.scatter(x, y, s=60, alpha=0.7, edgecolors="k")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_title('logarithmic scale for x/y axes')


fig.tight_layout() # 自动调整间距
plt.show()

8

引申-绘制曼哈顿图

代码语言:javascript
复制
# 曼哈顿图是散点图的一种变体,可联想曼哈顿鳞次栉比的大楼
# 一般用于基因相关研究,如GWAS。每组表示一个染色体,每个点表示一个基因
# x轴为该点在染色体的位置,y轴值代表其P值的-log10,越高相关性越强

from pandas import DataFrame
from scipy.stats import uniform
from scipy.stats import randint
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.cm as cm

mpl.rcParams.update(mpl.rcParamsDefault) # 恢复默认的matplotlib样式

# 自定义数据
df = DataFrame({'gene' : ['gene-%i' % i for i in np.arange(10000)],
                'pvalue' : uniform.rvs(size=10000),
                'chromosome' : ['ch-%i' % i for i in randint.rvs(0,12,size=10000)]})

# p值对数化
df['minuslog10pvalue'] = -np.log10(df.pvalue)
# 染色体组
df.chromosome = df.chromosome.astype('category') # 转category类型
df.chromosome = df.chromosome.cat.set_categories(['ch-%i' % i for i in range(12)], ordered=True) # 排序
df = df.sort_values('chromosome') # 数据排序

# 如何绘制基因与 -log10(pvalue) 的关系并按染色体着色
df['ind'] = range(len(df))
df_grouped = df.groupby(('chromosome'))

# 绘制曼哈顿图
fig = plt.figure(figsize=(14, 8))
ax = fig.add_subplot(111)
cmap = cm.get_cmap('rainbow', 12) # 获取调色板
colors = [cmap(i) for i in range(12)] # 分配颜色
x_labels = []
x_labels_pos = []

for num, (name, group) in enumerate(df_grouped):
    group.plot(kind='scatter', x='ind', y='minuslog10pvalue',color=colors[num % len(colors)], ax=ax)
    x_labels.append(name)
    x_labels_pos.append((group['ind'].iloc[-1] - (group['ind'].iloc[-1] - group['ind'].iloc[0])/2))
ax.set_xticks(x_labels_pos)
ax.set_xticklabels(x_labels)

# 设置轴
ax.set_xlim([0, len(df)])
ax.set_ylim([0, 3.5])
ax.set_xlabel('Chromosome')

plt.show()

9

引申-单轴散点图

代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random

# 自定义数据
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
hours = list(range(24))
sales_data = []

for day in days:
    for hour in hours:
        rand_num = random.random()  # 生成0-1之间的随机数
        if rand_num <= 0.8:  # 80%的概率生成0-100之间的销售量
            sales_volume = random.randint(0, 20)
        else:  # 20%的概率生成100-600之间的销售量
            sales_volume = random.randint(40, 500)
        sales_data.append([day, hour, sales_volume])

df = pd.DataFrame(sales_data, columns=['Day', 'Hour', 'Sales Volume'])


# 将一周的数据映射成数值类型,方便Y轴显示
day_to_num = {day: num for num, day in enumerate(days)}
df['Day_num'] = df['Day'].map(day_to_num)

# 创建一个新的figure
plt.figure(figsize=(10,6))

# 移除边框
spines = plt.gca().spines
for side in ['top','right']:
    spines[side].set_visible(False)

# 为每一天绘制散点图
for day in days:
    day_data = df[df['Day'] == day]
    plt.scatter(day_data['Hour'], day_data['Day_num'], s=day_data['Sales Volume'], label=day)

plt.yticks(np.arange(len(days)), days)    # 设置y轴的刻度和标签

# 自定义图里
plt.legend(bbox_to_anchor=(1.02,1), loc="upper left", borderaxespad=0)

plt.show()

14

如何避免过度绘制造成的散点重叠

适当处理样本

代码语言:javascript
复制
# 当数据集较大时,绘制散点图容易出现重叠造成不可读
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import seaborn as sns
import pandas as pd
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签

# 自定义数据
df=pd.DataFrame({'x': np.random.normal(10, 1.2, 20000), 
                 'y': np.random.normal(10, 1.2, 20000), 'group': np.repeat('A',20000) })
tmp1=pd.DataFrame({'x': np.random.normal(14.5, 1.2, 20000), 
                   'y': np.random.normal(14.5, 1.2, 20000), 'group': np.repeat('B',20000) })
tmp2=pd.DataFrame({'x': np.random.normal(9.5, 1.5, 20000), 
                   'y': np.random.normal(15.5, 1.5, 20000), 'group': np.repeat('C',20000) })
df=pd.concat([df,tmp1,tmp2], ignore_index=True)


# 初始化
fig = plt.figure(figsize=(8,8))

# 过度绘制
ax = plt.subplot2grid((2, 2), (0, 0), colspan=1)
plt.plot('x', 'y', "o", data=df, linestyle='')
ax.set_title('过度绘制')

# 减小标记与透明度
ax = plt.subplot2grid((2, 2), (0, 1), colspan=1)
plt.plot( 'x', 'y', "o", data=df, linestyle='', markersize=3, alpha=0.05, color="purple")
ax.set_title('减小标记与透明度')

# 2D密度图
ax = plt.subplot2grid((2, 2), (1, 0), colspan=1)
sns.kdeplot(data = df, x="x", y="y", cmap="Reds", fill=True)
ax.set_title('2D密度图')

# 样本采样
df_sample=df.sample(1000) # 样本采样
ax = plt.subplot2grid((2, 2), (1, 1), colspan=1)
plt.plot('x', 'y', "o", data=df_sample, linestyle='')
ax.set_title('样本采样')


fig.tight_layout() # 自动调整间距
plt.show()

10

分开观察

代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
import matplotlib.gridspec as gridspec

# 导入自定义模块
import SeabornFig2Grid as sfg

sns.set(font='SimHei', font_scale=0.8, style="darkgrid") # 解决Seaborn中文显示问题
 
# 自定义数据
df=pd.DataFrame({'x': np.random.normal(10, 1.2, 20000), 
                 'y': np.random.normal(10, 1.2, 20000), 'group': np.repeat('A',20000) })
tmp1=pd.DataFrame({'x': np.random.normal(14.5, 1.2, 20000), 
                   'y': np.random.normal(14.5, 1.2, 20000), 'group': np.repeat('B',20000) })
tmp2=pd.DataFrame({'x': np.random.normal(9.5, 1.5, 20000), 
                   'y': np.random.normal(15.5, 1.5, 20000), 'group': np.repeat('C',20000) })
df=pd.concat([df,tmp1,tmp2], ignore_index=True)

# 子图, 使用 gridspec 进行比例分配
fig = plt.figure(figsize=(8, 8))
gs = gridspec.GridSpec(2, 1, height_ratios=[4, 1])

# 绘制分组散点图
scatter1 = sns.lmplot( x="x", y="y", data=df, fit_reg=False, hue='group', 
               legend=False, palette="Accent", scatter_kws={"alpha":0.1,"s":15} )
scatter1.ax.legend(loc='lower right', markerscale=2)
scatter1.ax.set_title('分组散点图')

# 绘制分位面散点图
g = sns.FacetGrid(df, col="group", hue="group")
scatter2 = (g.map(plt.scatter, "x", "y", edgecolor="w"))
g.set_titles('分位面散点图-group {col_name}')
 
# 使用SeabornFig2Grid转换 seaborn 图为 matplotlib 子图
mg1 = sfg.SeabornFig2Grid(scatter1, fig, gs[0])
mg2 = sfg.SeabornFig2Grid(scatter2, fig, gs[1]) 
    
gs.tight_layout(fig)
plt.show()

11

抖动散点图

代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd

sns.set(font='SimHei', font_scale=0.8, style="darkgrid") # 解决Seaborn中文显示问题

# 自定义数据
a=np.concatenate([np.random.normal(2, 4, 1000), 
                  np.random.normal(4, 4, 1000), 
                  np.random.normal(1, 2, 500), 
                  np.random.normal(10, 2, 500), 
                  np.random.normal(8, 4, 1000), 
                  np.random.normal(10, 4, 1000)])
df=pd.DataFrame({'x': np.repeat( range(1,6), 1000), 'y': a })

fig, axs = plt.subplots(ncols=2, figsize=(8, 4)) # 创建1行2列的子图

# 原始散点图
axs[0].plot( 'x', 'y', "o", data=df, linestyle='')
axs[0].set_title('原始散点图')

# 抖动散点图
sns.stripplot(data =df, x="x", y="y", jitter=0.2, size=2, ax=axs[1])
axs[1].set_title('抖动散点图')

plt.tight_layout()
plt.show()

12

3D图

代码语言:javascript
复制
# 3D图
from scipy.stats import gaussian_kde
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.rcParams.update(mpl.rcParamsDefault) # 恢复默认的matplotlib样式
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签

# 自定义数据
nbins=300
k = gaussian_kde([df.x,df.y])
xi, yi = np.mgrid[ df.x.min():df.x.max():nbins*1j, df.y.min():df.y.max():nbins*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))
data=pd.DataFrame({'x': xi.flatten(), 'y': yi.flatten(), 'z': zi })

# 绘制3D图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(data.x, data.y, data.z, cmap=plt.cm.Spectral, linewidth=0.2)

ax.view_init(30, 80)

plt.title('3D图')
plt.show()

13

总结

以上通过seaborn的scatterplot和matplotlib的plot可以快速绘制散点图,并通过修改参数或者辅以其他绘图知识自定义各种各样的散点图来适应相关使用场景。

共勉~

参考资料

[1]

seaborn.scatterplot: https://seaborn.pydata.org/generated/seaborn.scatterplot.html

[2]

seaborn.regplot: https://seaborn.pydata.org/generated/seaborn.regplot.html

[3]

matplotlib.pyplot.plot: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HsuHeinrich 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关系(一)利用python绘制散点图
    • 散点图 (Scatterplot)简介
      • 快速绘制
        • 定制多样化的散点图
          • 通过seaborn绘制多样化的散点图
          • 通过matplotlib绘制多样化的散点图
        • 如何避免过度绘制造成的散点重叠
          • 适当处理样本
          • 分开观察
          • 抖动散点图
          • 3D图
        • 总结
          • 参考资料
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档