在 #26414 中,我们将 Pandas 绘图模块拆分为一个通用绘图框架,能够调用不同的后端和当前的 matplotlib 后端。 这个想法是其他后端可以以更简单的方式实现,并由 Pandas 用户与通用 API 一起使用。
当前 matplotlib 后端定义的 API 包括下面列出的对象,但这个 API 可能可以简化。 以下是问题/建议列表:
保留在 API 中的无争议方法(它们提供Series.plot(kind='line')
... 功能):
大熊猫提供的绘图功能(例如pandas.plotting.andrews_curves(df)
)
这些应该是 API 的一部分,其他后端也应该实现它们吗? 转换为.plot
格式(例如DataFrame.plot(kind='autocorrelation')
...)有意义吗? 远离 API 或转移到第三方模块是否有意义?
可以删除的冗余方法:
在boxplot
的情况下,我们目前有几种生成绘图的方法(主要调用相同的代码):
DataFrame.plot.boxplot()
DataFrame.plot(kind='box')
DataFrame.boxplot()
pandas.plotting.boxplot(df)
就个人而言,我会弃用数字 4,对于数字 3,弃用或至少不需要在后端使用单独的boxplot_frame
方法,但尝试重用BoxPlot
(对于数字 3 评论,相同适用于hist
)。
对于boxplot_frame_groupby
,没有详细检查,但不确定BoxPlot
是否可以重复使用?
注册转换器的函数:
这些对其他后端有意义吗?
在 pandas 0.23 中已弃用,待删除:
要查看这些函数在实践中的作用, @liirusuk 的这个笔记本可能很有用: https :
抄送:@pandas-dev/pandas-core @ tacaswell 、 @jakevdp 、 @philippjfr 、@PatrikHlobil
我认为将自相关之类的东西排除在可交换后端 API 之外。
我认为我们保留了 df.boxplot 和 hist 之类的东西,因为它们的行为与 .plot API 略有不同。 我不建议将它们作为后端 API 的一部分。
这是我几个月前提出的后端 API 的开始: https :
我认为值得一提的是,至少hvplot
(没有检查其余部分)确实已经提供了诸如andrews_curves
、 scatter_matrix
、 lag_plot
。 ..
可能是如果我们不想强制所有后端实现这些,我们可以检查所选后端是否实现它们,并默认为 matplotlib 图?
我假设boxplot
和hist
行为完全相同,但只有Series.plot.hist()
快捷方式Series.hist()
Series.plot.hist()
。 “快捷方式”显示了绘图网格,但除此之外我没有看到任何区别。
IMO,此选项的主要值是.plot
命名空间。
如果用户想要 hvplot 的安德鲁曲线图,他们应该导入函数
从 hvplot 并在那里传递数据框。
在 2019 年 6 月 9 日星期日上午 7 点 17 分,Marc Garcia [email protected]写道:
我认为值得一提的是,至少 hvplot(没有检查
休息)确实已经提供了像andrews_curves这样的功能,
scatter_matrix、lag_plot、...可能是如果我们不想强制所有后端都实现这些,我们可以
检查所选后端是否实现它们,并默认为
matplotlib 绘图?我假设 boxplot 和 hist 的行为完全相同,但只是有
Series.plot.hist() 的快捷方式 Series.hist()。 “快捷方式”显示
绘图网格,但除此之外我没有看到任何区别。—
您收到此消息是因为您所在的团队已被提及。
直接回复本邮件,在GitHub上查看
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOIRLJHBMXMXKK2IG2NDPZTYFPA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63KDMX700000000000000000000000和
或静音线程
https://github.com/notifications/unsubscribe-auth/AAKAOISDHL6H7PVOOJAQXELPZTYFPANCNFSM4HWIMEKQ
.
我认为这是有道理的,但如果我们这样做,我认为我们应该将它们移动到pandas.plotting.matplotlib.andrews_curves
,而不是pandas.plotting.andrews_curves
。
@TomAugspurger我需要更详细地检查,但我认为你在https://github.com/TomAugspurger/pandas/commit/b07aba28a37b0291fd96a1f571848a7be2b6de8d 中实现的 API 更有意义。 完成#26753 后,我将继续努力。 我还将尝试将andrews_curves
、 scatter_matrix
... 移动到.plot()
语法是否可行,我认为这将使每个人(我们、第三方库和用户)。
这里关于传递给绘图函数的额外 kwargs 的意图是什么? 其他后端是否应该尝试复制所有 matplotlib 样式的绘图自定义的功能,还是应该允许传递与特定后端使用的关键字相对应的关键字?
第一个选项在理论上会很好,但需要每个非 matplotlib 绘图后端基本上实现自己的 matplotlib 转换层,其中包含一长串的不兼容问题,这些问题基本上永远不会完成(从尝试创建 mpld3 的人的经验说起)几年前)。
从可互换性的角度来看,第二个选项不太好,但可以允许添加其他后端并具有更合理的期望。
我认为这取决于后端如何处理它们。 实现 100%
跨后端的兼容性并不真正可行,
因为返回类型不再是 matplotlib Axes。 而如果
我们在返回类型上不兼容,我不认为后端
应该向后弯曲以尝试处理每个可能的关键字参数。
所以我认为熊猫应该记录**kwargs
将被传递给
底层绘图引擎,他们可以随心所欲
他们。
2019 年 6 月 10 日星期一上午 10:42 Jake Vanderplas [email protected]
写道:
关于传递给绘图的额外 kwargs 的意图是什么
职能? 如果其他后端尝试复制
所有 matplotlib 样式的绘图自定义的功能,或者它们应该
允许传递与特定对象使用的关键字相对应的关键字
后端?第一个选项理论上很好,但需要每个
非 matplotlib 绘图后端基本上实现了自己的 matplotlib
具有长尾不兼容性的转换层
基本上永远不会是完整的(从经验来说
几年前曾尝试创建 mpld3)。从的角度来看,第二种选择并不好
可互换性,但允许其他后端添加更多
合理的预期。—
你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOIS3IBV4XSSY7BPSCF3PZZY5LA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43MVVMVBWZKLOM504MVVMVBWZKLOM504MVWWWWZKLOM504MVWWWWZHW500XHW500X52000000001
或静音线程
https://github.com/notifications/unsubscribe-auth/AAKAOIQ3GYOGAPUZ4LSNK2DPZZY5LANCNFSM4HWIMEKQ
.
如果这是一个愚蠢的问题,我很抱歉,但是如果您定义一个绘图“API”,它基本上是一组罐头绘图,是不是每个后端都会产生或多或少相同的输出? 这意味着要启用什么新功能? 像熊猫到vega出口商之类的东西?
我认为说每个后端产生或多或少相同的输出是不正确的。
例如,matplotlib 非常擅长静态图表,但不擅长制作便携式交互式图表。
另一方面,散景、altair 等。 非常适合交互式图表,但不如用于静态图表的 matplotlib 成熟。
能够使用相同的 API 生成两者将是一个巨大的胜利。
第一个选项在理论上会很好,但需要每个非 matplotlib 绘图后端基本上实现自己的 matplotlib 转换层,其中包含一长串的不兼容问题,这些问题基本上永远不会完成(从尝试创建 mpld3 的人的经验说起)几年前)。
并且将 Matplotlib 固定得比我们已经知道的 API 还要多。 我认为 Pandas 声明它想要公开的样式旋钮是有道理的,并期望后端实现能够弄清楚这意味着什么。 这可能意味着_不_盲目地传递**kwargs
,而是确保返回的对象是给定后端的“正确事物”,以便能够进行事后样式定制。
例如,matplotlib 非常擅长静态图表,但不擅长制作便携式交互式图表。
谢谢@jakevdp ,是的,支持交互式图表是一个很好的目标。
在事情走得太远之前,这里有一个替代解决方案。
与其宣布 Pandas 绘图 API 现在是一个规范,并要求可视化包专门实现它,为什么不生成绘图的中间表示(如 vega JSON 文件),并鼓励后端将其作为他们的输入。
优点包括:
Vega/Vega-lite作为一种现代的、成熟的、开放的、基于 JSON 的可视化规范语言,在设计和实现中投入了数年的时间,并且围绕它构建的现有工具似乎是专门为此目的而创建的. (只是请不要)。
你知道, frontend->IR->backend
,就像编译器的设计。
至少三个包已经实现了 API。 pandas 需要做的就是提供一个选项来更改后端并记录其使用,这对我们来说似乎是一个不错的选择。
在2019年6月15日,在16:28,pilkibun [email protected]写道:
例如,matplotlib 非常擅长静态图表,但不擅长制作便携式交互式图表。
谢谢@jakevdp ,是的,支持交互式图表是一个很好的目标。
在事情走得太远之前,这里有一个替代解决方案。
与其宣布 Pandas 绘图 API 现在是一个规范,并要求可视化包专门实现它,为什么不生成绘图的中间表示(如 vega JSON 文件),并鼓励后端将其作为他们的输入。
优点包括:
不受具体化的 Pandas API 的表达能力的束缚,该 API 不是作为规范设计的。
通过绘制支持 Pandas 的包完成的工作可用于其他生成 IR 的 pydata 包。
在 pydata 空间中推广一种用于交换可视化的通用语言
这使得新工具更强大,因为适用范围更广
这使得编写它们的努力更加合理。 基本上,改进的激励措施。
Vega/Vega-lite,作为一种现代的、成熟的、开放的、基于 JSON 的可视化规范语言,在其设计和实现中投入了数年的时间,并且围绕它构建的现有工具似乎是专门为此目的而创建的. (只是请不要)。要知道,frontend->IR->backend,就像编译器的设计。
—
你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看,或将线程静音。
我们现在合并了#26753,并且可以从pandas 更改绘图后端。 当我们拆分 matplotlib 代码时,我们将SeriesPlotMethods
和FramePlotMethods
留在了熊猫(不是 matplotlib)一侧。 这主要是为了将文档字符串留在熊猫这边。
但我看到后端所做的是重新实现这些类。 所以,目前我们希望后端每个图有一个类(例如LinePlot
, BarPlot
),但是他们实现了一个每个方法都有一个图的类(例如hvPlot, or the same names as pandas for
pdvega `)。
我认为有意义的,至少作为第一个版本,是我们按照hvplot
和pdvega
实现的 API。 我只是在熊猫中创建一个抽象类,后端继承自。
如果这对每个人都有意义,我将首先创建抽象类并调整我们在 Pandas 中的 matplotlib 后端,一旦完成,我们调整hvplot
和pdvega
(更改应该很小)。
想法?
我认为有意义的,至少作为第一个版本,是我们像 hvplot 和 pdvega 那样实现 API。 我只是在熊猫中创建一个抽象类,后端继承自。
我认为总的来说,这种方法会更干净。 我无法与其他绘图后端交谈,但至少在 hvPlot 中,不同的绘图方法共享相当多的代码,例如scatter
、 line
和area
基本上是类似的,并且我不想依赖子类在它们之间共享代码。 此外,我认为不同的后端应该可以选择添加额外的绘图类型,并将它们作为额外的公共方法公开似乎是最简单、最自然的方法。
只是为了确保我理解,当你说I'd prefer not to rely on subclassing to share code between them
你的意思是像class LinePlot(MPLPlot)
,对吧? 不是说您认为从抽象基类继承是一个坏主意吗?
我想我对让后端定义不在 Pandas 中的绘图类型持 +1 意见。 但我现在可能不会实施它。 我们计划在一周左右发布熊猫。 而且我认为如果用户提供kind='foo'
并且后端提供方法foo
(例如,参数验证,否则会导致一些kind
将在文档中,有些则不会)。
只是为了确保我理解,当您说我不想依赖子类化在它们之间共享代码时,您的意思是像 LinePlot(MPLPlot) 类中那样,对吗? 不是说您认为从抽象基类继承是一个坏主意吗?
恩,那就对了。 更具体地说,我宁愿不必做这种事情:
class MPL1dPlot(MPLPlot):
def _some_shared_method(self, ...):
...
class LinePlot(MPL1dPlot):
...
class AreaPlot(MPL1dPlot):
...
抱歉,如果不清楚。
非常赞成更简单的 API,它作为单个函数而不是现在在https://github.com/pandas-dev/pandas/pull/27009 中提出的类公开公开
关于后端选项现在如何工作的一般问题/评论。 假设我是pdvega
开发人员,并让这个后端可用。 这意味着如果用户执行pd.options.plotting.backend = 'pdvega'
,那么pdvega
库需要具有顶级plot
函数吗?
1) 作为库作者,这不一定是您想要公开的功能(也就是说,对于从库的角度来看的顶级plot
方法,不一定是您希望用户使用的 API直接使用) 和 2) 对于这种情况,您实际上可能希望能够执行pd.options.plotting.backend = 'altair'
? (以防 Altair 开发人员对此感到满意)
所以基本上我的问题是:后端名称和导入的内容是否需要精确的 1:1 映射? (现在需要它,因为它只是导入提供的后端字符串)。
编辑:我看到 PR #26753 中实际上讨论了类似的内容
如果我们决定 pandas 不知道/限制可以使用哪些后端(我强烈支持这样做),我们需要决定如何/在后端调用什么。
它在我正在处理的 PR 中实现和提出的是选项plotting.backend
是一个模块(可以是pdvega
、 altair
、 altair.pandas
,或其他),并且该模块必须具有公共plot
函数,我们将调用该函数。
我们可以考虑其他选项,比如如果选项是pdvega
,我们导入pdvega.pandas
,或者我们可以命名函数plot_pandas
或其他什么。 我认为建议的方式是最简单的,但如果有其他更有意义的建议,我很乐意更改它。
另一个讨论是我们是否要强制用户手动导入后端:
import pandas
import hvplot
pandas.Series([1, 2, 3]).plot()
如果我们这样做,模块可以注册自己,它们也可以注册别名(因此set_option
可以理解模块名称以外的其他名称)。 他们还可以实现自定义功能或机制(例如上下文管理器)以使用某些后端进行绘图,...我个人认为,我们保持的东西越简单越好。
虽然用pandas.set_option('plotting.backend', 'bokeh')
在散景中绘图可能会很好,但我认为这意味着我个人不喜欢的两件事:
pandas.set_option('plotting.backend', 'bokeh')
仅在调用了import pandas_bokeh
时才有效,并且会使用户感到困惑。bokeh
只有一个模块可以绘制。 这不一定是真的,并且会给用户错误的印象,即您直接使用散景绘制,而不是使用 Pandas 绘制散景后端。@datapythonista感谢您的详细回答。 我现在可以将它保留为初始版本(以后总是可以添加别名的可能性)。
如果用户想要 hvplot 的安德鲁曲线图,他们应该从 hvplot 导入函数并将数据框传递到那里。
+1,我也不会通过后端公开所有额外的绘图功能。
但是关于将它们移动到pandas.plotting.matplotlib
,这对我来说似乎是一个不必要的向后不兼容的中断(假设您的意思不仅是移动实现)。
pandas.set_option('plotting.backend', 'bokeh') 仅在调用了 import pandas_bokeh 时才有效,并且会让用户感到困惑。
如果我们使用入口点来注册扩展,则不必如此:将包安装在系统上将注册入口点并使其对 Pandas 可见。 例如,这是 Altair 用来检测用户可能已安装的各种渲染器的工具。
此外,对于它的价值,一旦进入我想我可能会弃用 pdvega 并将相关代码移到一个名为pandas_altair
或类似的新包中。
@datapythonista我认为我们应该在 0.25.0 之前决定绘图后端 API 的范围(但不适用于 RC)。
您赞成保留 misc 绘图函数(以及 hist / boxplot)?
@datapythonista在我们合并 PR 时关闭它?
@jreback在我们就 API 达成一致之前,我会一直保持开放, @TomAugspurger和@jorisvandenbossche除了访问器图之外不想将任何内容委托给后端。
我会为绘制熊猫做什么 - 后端是下一个。
对于发布:
register_matplotlib_converters
更改为我们委托他们对于下一个版本:
pandas.plotting.boxplot
, Series.hist
,...对于后端 API 的初始版本,我宁愿在我们公开的内容上更加保守,而不是包含所有内容。 稍后添加东西比删除要容易得多。
我个人也不会将所有这些杂项图移动到访问器(可能有一些例外,例如散点矩阵),IMO 的 andrew_curves 和 radviz 等不“值得”使用一种方法。
也就是说:我们是否希望允许后端实现额外的“种类”? 因此,作为熊猫,我们不必确切地决定哪些访问器方法可用。 如果用户传递了某个kind
或尝试访问一个属性,我们仍然可以使用自定义__getattribute__
将它传递给后端plot
__getattribute__
。
只是为了解释一下为什么事情会变成现在这样。 这是相关的,因为我不太确定如何实施您提出的更改,或者不公开一般情况。 这里不是说不能以不同的方式完成,只是为了丰富讨论。
第一个决定是将使用 matplotlib 的所有代码移动到一个单独的模块 ( pandas.plotting._matplotlib
)。 通过这样做,该模块以某种方式成为了 matplotlib 后端。
pandas.plotting
中公开的所有内容都在那里保持公开。 为了让事情尽可能简单,这些函数中的每一个,一旦被调用,它就会加载后端(调用_get_plot_backend
)并在那里调用函数。
用户的公共API没有任何变化,用户仍然可以使用相同的方法和功能。 我们不会暴露任何新的东西。
我的理解是,如果我们决定不将像andrew_curves
这样的现有绘图委托给后端,这意味着不是让用户选择后端,我们仍将选择 matplotlib 后端。 鉴于至少hvplot
已经在实施andrew_curves
,我个人不明白这一点。 如果用户想要 matplotlib 中的andrew_curves
绘图,就像不更改后端一样简单(如果更改了,则再次设置)。 因此,通过更改,我们所做的只是通过为 Pandas 增加额外的复杂性,让用户的生活变得更加艰难。
如果我们想与后端开发人员友好相处,而不是强迫他们实现可能不是那么主流的图(我想这是原因之一?),也许我们可以将所选后端中缺少的任何内容默认为 matplotlib 后端?
关于将任何未知类型的情节委派给后端,我现在做的 -1。 当然,它最终会有意义。 但是我认为在 Pandas 中记录了几种情节类型,并且有我们没有记录的额外情节,感觉有点麻烦。 我觉得可以等下个版本,等我们反馈了不同的后端如何为用户工作之后,我们有更多的时间来详细讨论和分析。
如果用户想要 matplotlib 中的 andrew_curves 图,就像不更改后端一样简单(如果更改了,则再次设置)。 因此,通过更改,我们所做的只是通过为 Pandas 增加额外的复杂性,让用户的生活变得更加艰难。
我认为我们不会让用户的生活变得更艰难。 如果他们想要一个 hvplot 的版本,而不是从 pandas.plotting 导入它,他们可以简单地从那里导入它。 这对于 DataFrame.plot 方法来说是不可能的,因为它是在对象上定义的。 对我来说,这是绘图后端的主要原因。
如果我们想与后端开发人员友好相处,而不是强迫他们实现可能不那么主流的情节
对我来说,这不是为了好看或需要实现所有东西(如果后端不支持所有绘图类型,IMO,那完全没问题),而是绘图后端 API 的不必要扩展,这也将我们与它联系起来.
如果我们从头开始重新启动 Pandas,我认为不会包括那些杂项绘图类型。 但是通过绘图后端 API,我们在某种程度上开始了一些新的事情。
对此还有其他意见吗?
@jorisvandenbossche您将如何更改代码中的内容? 不是获取在这些方法的设置中定义的后端,而是获取 matplotlib 后端? 我认为这在概念上是错误的,但如果达成一致,我可以接受。 任何恢复 matplotlib 代码与其余代码解耦的东西我都是 -1。
既然你从头开始提到在熊猫中我们不会包括这些情节,我们应该弃用它们吗? 我对将所有不是Series
或DataFrame
方法的图移动到第三方包表示支持。 或者,如果有任何重要到需要保留,将其移动到.plot()
作为其他调用。
我会弃用熊猫中的非标准图
并移动到外部包
Joris 离线了一段时间。
我认为,当我们过去讨论过这个问题时,他和我在论文上的立场是让它们保持原样,直到它们成为维护负担。
就这样我们在同一页面上,这是我们所拥有的摘要以及我对讨论状态的理解:
用作Series
和DataFrame
(我们很高兴将它们保持原样,委托给选定的后端):
其他图(正在讨论是否应该弃用、委托给 matplotlib 后端或委托给选定的后端):
pandas.plotting
其他公共内容(也在讨论中):
对于Other plots
部分,我个人认为在这一点上它们是维护负担,并且我对将它们从 Pandas 中移出 +1,并在 0.25 中弃用它们。
对于转换器和其他东西,我们现在拥有的肯定是不正确的,因为register_matplotlib_converters
委托给选定的情节,这不能是 matplotlib。 我想我们可以考虑的选项是:
register_converters
/ deregister_converters
,弃用当前的,并继续委托给后端pandas.plotting
到pandas.plotting.matplotlib
(这意味着将 matplotlib 后端公开,所以我不会)pandas.plotting
知道存在哪些后端)对于其他图部分,我个人认为此时它们是维护负担,我对将它们从 Pandas 中移出 +1,并在 0.25 中弃用它们。
您如何发现“其他地块”成为维护负担? 查看“misc”图的历史: https :
将它们重命名为 register_converters/deregister_converters,弃用当前的,并继续委托给后端
我认为这没有意义。 我们为 matplotlib 编写了特定于 matplotlib 的转换器。 其他后端不会有它们。 它可能不应该是后端 API 的一部分。
我并不是说这些图是一种负担,因为我们在过去几个月中进行了大量维护,而是因为他们认为现在为用户提供一致且直观的 API 以及良好的模块化为我们设计代码。
关于转换器,我不知道后端作者是否可能希望在某些情况下实现与 matplotlib 等效的转换器。 但是如果他们不这样做似乎没有问题,并且这些功能对某些或所有其他后端没有任何作用。 我也同意选项 2,但我觉得它不那么整洁。
但是因为他们认为现在的问题是为用户提供一致且直观的 API,以及为我们提供良好的模块化代码设计。
不过,它们与 DataFrame.plot 已经有些不一致了。 “misc”这个名字暗示:) 有一个可交换的后端会使情况变得更糟吗? 在多大程度上值得用户代码流失? 我不这么认为。
我不知道在某些情况下后端作者是否可能想要实现与 matplotlib 等效的那些。
我不这么认为。 这些转换器的重点是教 matplotlib 关于 Pandas 对象。 实现后端的库不会有这个问题,因为它们已经依赖于 Pandas。
我个人主要从管理复杂性的角度来考虑它。 拥有通过单个 API 委托给后端的标准绘图 API 很容易理解和维护。 用户和维护者只需要知道有一个带有kind
参数的plot
函数,并且这将在选定的后端执行。
在后端有一组异构图,除了不遵循相同的 API 外,还使用后端,但不是为其他图选择的后端,而是 Matplotlib 的后端,恕我直言,为每个人增加了太多的复杂性。
移动它们的成本对我来说似乎很小,我的猜测是我们的用户中没有很大一部分甚至知道这些地块。 对于那些这样做的人,他们只需要安装一个额外的 conda 包并使用import pandas_plotting; pandas_plotting.andrews_curves(df)
而不是pandas.plotting.andrews_curves(df)
。
对我来说,以很小的代价赢得很多东西,但这当然只是一种意见。
我们能否证明可交换后端仅用于 Series/DataFrame.plot? 这似乎是一个非常简单的规则。
感觉就像一个 hack,给我增加了不必要的复杂性; 我认为在文档中解释它不会让它不那么违反直觉。
但无论如何,也没什么大不了的。 如果这是首选选项,这就是我实现它的方式,至少代码复杂性的增加是最小的:#27432
现在更仔细地观察:如果我理解正确,绘图后端的设置方式是使用:
pd.set_option('plotting.backend', 'name_of_module')
那么,我的理解是,如果我想做以下工作:
pd.set_option('plotting.backend', 'altair')
那么我将需要顶级 altair 包来定义https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/_core.py 中的所有函数
如果我理解正确,这意味着我无法使pd.set_option('plotting.backend', 'altair')
正常工作,而无需像 matplotlib 当前硬编码的方式那样在 pandas 中对 altair 包进行硬编码,对吗?
如果是这样,我强烈建议重新考虑在第三方包中公开此 API 的方式。
我建议的解决方案是采用基于入口点的框架,例如,它可以让我创建一个像altair_pandas
这样的包,它注册altair
入口点来实现 API。 否则,用户将永远对pd.set_option('plotting.backend', 'altair')
没有按照他们的期望行事感到困惑。
同意。 我认为切入点是要走的路。 我会做一些原型。
2019 年 7 月 19 日星期五下午 1:16 Jake Vanderplas通知@ github.com
写道:
现在更仔细地观察:如果我理解正确,那么
绘图后端将使用:pd.set_option('plotting.backend', 'name_of_module')
那么,我的理解是,如果我想做以下工作:
pd.set_option('plotting.backend', 'altair')
那么我将需要顶级的 altair 包来定义所有的功能
在
https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/_core.py。
我不想用所有这些来污染 Altair 的顶级命名空间
额外的 API。 事实上,我更喜欢 altair 的 pandas 扩展
存在于一个单独的包中,因此它与发布节奏无关
牛郎星本身。如果我理解正确,这意味着我无法制作 pd.set_option('plotting.backend',
'altair') 无需在 pandas 中对 altair 包进行硬编码即可正常工作
matplotlib 目前是硬编码的,对吗?如果是这样,我强烈建议重新考虑如何实现这一点
第三方包。 特别是,采用基于入口点的框架
会让我创建一个像 altair_pandas 这样的包来注册 altair
入口点。 否则用户将永远对 pd.set_option('plotting.backend',
'altair') 不符合他们的预期。—
你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOITQM7HH5X4SZ4IAPS3QAIAIBA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2ML5OQ#issuecomment-513326778 ,
或静音线程
https://github.com/notifications/unsubscribe-auth/AAKAOISFLHDGXLGQ3PUMNLDQAIAIBANCNFSM4HWIMEKQ
.
曾几何时,您所说的大部分是正确的,但现在情况不再如此。
如果你想要pandas.options.plotting.backend = 'altair'
,在 0.25 你只需要有一个函数altair.plot()
。 在某些时候,我认为调用函数pandas_plot
而不是简单的plot
会更好,因此它在具有其他功能的后端中是特定的,但我们最终没有进行更改。
如果在 altair 的顶层创建plot
函数有问题,我们可以在以后的版本中重命名它,或者您也可以使用altair.pandas.plot
,但是用户必须设置pandas.options.plotting.backend = 'altair.pandas'
。
一旦用户执行import altair
您当然可以自己更改选项。 我们可以实现一个后端注册表。 但是我认为如果用户执行pandas.options.plotting.backend = 'altair'
并且失败了,那会让用户感到困惑,因为他们之前忘记了import altair
。
最后一件事是考虑我们可能为 altair(或任何其他可视化库)实现了多个 Pandas 后端。 所以,对我来说,后端的名称不是altair
,不一定是坏事。
这是一个基于入口点的实现
diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py
index 0610780ed..c8ac12901 100644
--- a/pandas/plotting/_core.py
+++ b/pandas/plotting/_core.py
@@ -1532,8 +1532,10 @@ class PlotAccessor(PandasObject):
return self(kind="hexbin", x=x, y=y, C=C, **kwargs)
+_backends = {}
-def _get_plot_backend(backend=None):
+
+def _get_plot_backend(backend="matplotlib"):
"""
Return the plotting backend to use (e.g. `pandas.plotting._matplotlib`).
@@ -1546,7 +1548,14 @@ def _get_plot_backend(backend=None):
The backend is imported lazily, as matplotlib is a soft dependency, and
pandas can be used without it being installed.
"""
- backend_str = backend or pandas.get_option("plotting.backend")
- if backend_str == "matplotlib":
- backend_str = "pandas.plotting._matplotlib"
- return importlib.import_module(backend_str)
+ import pkg_resources # slow import. Delay
+ if backend in _backends:
+ return _backends[backend]
+
+ for entry_point in pkg_resources.iter_entry_points("pandas_plotting_backends"):
+ _backends[entry_point.name] = entry_point.load()
+
+ try:
+ return _backends[backend]
+ except KeyError:
+ raise ValueError("No backend {}".format(backend))
diff --git a/setup.py b/setup.py
index 53e12da53..d2c6b18b8 100755
--- a/setup.py
+++ b/setup.py
@@ -830,5 +830,10 @@ setup(
"hypothesis>=3.58",
]
},
+ entry_points={
+ "pandas_plotting_backends": [
+ "matplotlib = pandas:plotting._matplotlib",
+ ],
+ },
**setuptools_kwargs
)
我觉得还不错。 第 3 方软件包将修改它们的 setup.py(或 pyproject.toml)以包含类似的内容
entry_points={
"pandas_plotting_backends": ["altair = pdvega._pandas_plotting_backend"]
}
我喜欢它打破命名和实现之间的紧密耦合。
我没有使用入口点,它们像 Python 环境的全局注册表吗? 作为他们的新手,我不喜欢这个想法,但我想那将是一个合理的方法。
我仍然希望同时拥有这两个选项,因此如果用户执行pandas.options.plottting.backend = 'my_own_project.my_custom_small_backend'
则它可以工作,并且不需要创建包和设置入口点。
我没有使用入口点,它们像 Python 环境的全局注册表吗?
我也没有使用它们,但我认为这就是想法。 据我了解,它们来自 setuptools(但是像 flit 这样的包被钩住了?)。 所以它们不是标准库的一部分,但 setuptools 是每个人都使用的。
我还是想同时拥有这两种选择
回到import_module(backend_name)
似乎是合理的。
最有用的评论
这是一个基于入口点的实现
我觉得还不错。 第 3 方软件包将修改它们的 setup.py(或 pyproject.toml)以包含类似的内容
我喜欢它打破命名和实现之间的紧密耦合。