【问题标题】:How to fasten scatterplot of seaborn when there is a big data(many points) to plot?当有大数据(很多点)要绘制时,如何固定seaborn的散点图?
【发布时间】:2021-11-19 16:49:35
【问题描述】:

当需要绘制大量数据点时,我发现Python中的seaborn.scatterplot()方法比R中ggplot2的函数geom_point慢很多。

例如Python中的相同数据(seaborn):

sample_data = data.sample(10000)
ax = sns.scatterplot(data=sample_data, x="x", y="y", hue="cate")

在 R(ggplot2) 中:

sample_data <- data[sample(nrow(data),10000),]
p <- ggplot(sample_data,aes(x=x,y=y)) +
    geom_point(aes(color=cate))

前者比后者慢很多。

我想知道是什么导致了效率的差异以及如何使seabornggplot 一样快甚至更好?

我为什么不直接使用 R:我更喜欢 Python 的语法风格,我可以在使用 seaborn 绘图后使用 matplotlib 进行更多自定义,而 ggplot 这样做可能不那么方便。

【问题讨论】:

  • 请注意,您正在使用 hue 参数调用 sns.scatterplot,而 R 代码中不会发生这种情况。如果有大量“cate”值,事情可能会变慢(在这种情况下,请尝试legend=False)。此外,如果 data 有一个非唯一索引,最新的 seaborn 版本似乎很慢(这可以通过 sns.scatterplot(data=sample_data.reset_index(), ....) 缓解)。反正10_000个点比较小,seaborn可以轻松画出百万个散点。 (顺便说一句,你创建了sample_data,但不使用它。data 有多大?)
  • @JohanC 非常感谢您的评论!我用hue 参数和geom_point 中的color 参数调用sns.scatterplot。它们之间有什么区别吗? data 有 600 万行左右,我还没有尝试直接将它们全部绘制出来(我不知道 sns 在可接受的时间内如何处理大数据)。
  • 您仍然使用原始的data 调用sns.scatterplot,而不是使用sample_data(至少在显示的代码片段中)。 Seaborn 的hue 代码在速度上并不总是最佳的。你没有提到有多少种不同的色调,但你可以试试legend=False。如果速度真的很重要,也可以直接调用matplotlibplt.scatter('x', 'y', c='cate', data=data)
  • @JohanC 哦,是的,这是一个错字。你是对的,legend=False 让它更快,而原生的plt.scatter 更快。有 10-20 种不同的色调,我现在相信 hue 和传说是让它变慢的原因。速度非常重要,因为该项目是针对网站的,而不仅仅是个人学术研究。非常感谢!
  • 在我的笔记本电脑上使用 ggplot2 和 seaborn(53K 行)内置的 diamonds 数据集进行测试,scatterplot(diamonds, x="carat", y="price", hue="color") 运行时间为 200 毫秒,而 ggplot(diamonds, aes(c=carat, y=price, color=color)) + geom_point() 运行时间为 1700 毫秒(并且似乎需要更长的时间在 RStudio 中实际渲染。所以我认为您需要 a) 共享您的数据,或使用内置数据集进行测试,b) 显示您正在做的事情的完整可重现示例,以及 c) 获得一些定量的时序估计。

标签: python r matplotlib ggplot2 seaborn


【解决方案1】:

要绘制“大数据”散点,我建议Plotly 库。 它有一个Scattergl 函数来管理多达数十亿的数据点。

这是一个包含 100.000 个数据点的示例:

import plotly.graph_objects as go
import numpy as np

N = 100000
r = np.random.uniform(0, 1, N)
theta = np.random.uniform(0, 2*np.pi, N)

fig = go.Figure(data=go.Scattergl(
    x = r * np.cos(theta), # non-uniform distribution
    y = r * np.sin(theta), # zoom to see more points at the center
    mode='markers',
    marker=dict(
        color=np.random.randn(N),
        colorscale='Viridis',
        line_width=1
    )
))

fig.show()

结果:

【讨论】:

  • 太酷了!我试试看!
猜你喜欢
  • 2019-09-26
  • 2022-01-21
  • 2021-02-20
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多