槽点1:函数API过于丰富,命名不够直观易懂;有时又缺少一些有用的API
Pandas为了提供丰富的API、方便使用者的灵活调用,在设计上提供了大量繁杂的小功能和小技巧,但其实过犹不及,有时提供了过多的API在提供了丰富性的同时也给使用者带来一定的困扰,致使容易遗忘甚至混淆部分API的功能。例如:
以Pandas核心数据结构DataFrame为例,其一大特色是支持行列索引,然而在索引相关操作时,包括的API有reset_index、set_index、reindex、reindex_like、rename、rename_axis等等,至少在自己初学时对这index相关的函数懵圈了好久。相比之下,同样是以DataFrame为核心数据抽象的Spark.sql组件,其API则尤为简洁易懂。当然了,Spark里的DataFrame没Pandas的复杂是客观事实,Pandas里丰富的API也确实有其独特用武之地,所以也不能完全算是槽点。
如果说Pandas的API足够丰富是其一大优势,但在有些情况下又不尽然。Pandas在判断元素取值是否为空值时提供了互补的四个API,分别是isna、isnull、notna、notnull,这确实也是符合其API丰富的特点;但在处理元素是否属于某集合的API时,按理说也应当提供互补的操作,例如isin和notin,然而实际情况却是只有isin,当然notin是可以简单的在isin前加元素取反来实现,所以Pandas的API设计原则到底是要精练还是方便!
槽点2:部分功能用法不尽统一
这里就举一个小例子,就是Pandas内置了一些可视化功能,具体来说是对于DataFrame而言可直接调用部分绘图接口实现快速简单可视化。例如对于一个DataFrame,直接调用plot函数,通过设置kind参数可实现11种常用图表的可视化输出(默认基于matplotlib):
通过df.plot接口可实现11种绘图类型
然而,熟悉Pandas可视化操作的一定知道还有一种方式是直接通过df调用相应绘图接口的简洁形式,例如df.hist等等。然而,不幸的是这种简介的调用方法只对个别图表有用,大部分是不支持的。例如scatter。但问题是两种调用方式有什么本质区别吗?为何第二种要少支持一些图表类型呢?
槽点3:函数的参数名风格混乱
程序员都知道良好的变量命名其意义有多么的重要,自己在编写一些小功能函数时对于函数名、参数名等也是绞尽脑汁,既要简洁又要直观易懂。但在Pandas的有些函数中,参数名其实是比较混乱的。例如在读取数据时最为常用的pd.read_csv函数,其提供了大量的个性化参数配置,所以在使用起来更为灵活多样。但其参数命名却实在不敢恭维:
例如,对于多个单词组成的参数名,按照python的惯例应该是用蛇形命名法吧,但为什么skipinitialspace=False, skiprows=None, skipfooter=0这些又不用?对于参数可能是列表或字典等集合类的,那么参数名应该用单词的复数形式吧,例如names、usecols这些,但为什么dtype和date_parser这些也可能是集合传参的又用的单数?终究还是感觉有失严谨!
当然,最后个人还是要声明立场,我一直都是一个Pandas爱好者,也一直享受着Pandas对数据处理带来的便利,所以这些吐槽可能还是出于希望其更好迭代改进的期盼吧!