Tableau数据桶使用问题,求解惑~
例如:数据源每行都有销售人员、销售部门字段、销售额,创建数据桶默认按照子类别即销售人员做数据桶,如何能按照销售部门字段做数据桶呢?
求看,感激不尽
1、直觉的解决方法
既然是要把分钟标记为0,15,30,45四个部分,直觉的解决方法就是根据分钟的大小做判断(if else)。如下:
虽然说直觉在大部分情况下是对的,但是对于新手而言,大部分情况下似乎是有瑕疵的。
2、我的思考方法正好我路上看到这里,脑海中想了一个图,我们是想把分钟切分为四个部分,相当于数据桶又不能用Tableau的“数据桶”,因为数据桶在Tableau是把连续的度量切分用的,而这里是时间——维度。
上面的使用if else嵌套的方法,虽然可行,但显然效率太低,会给服务器沉重的压力——每一行都要做非常多的类型提取、转化、组合和判断。
这个问题之前有人问过我,不过当时是把1小时切分为2份,所以可以直接用上面的判断——只有两份使用的布尔运算,性能是最好的。这里要切分四分就不能用布尔运算,但是逻辑判断性能又太低。有没有更好的办法,比如用一次算数运算解决这个问题?
我突然想起来前几天在学习python写期货数据遇到的一个问题:
我的某个tushare接口一分钟不能提取120次,超过就会中断,为了避免中断,我设置了一个变量i,每循环一次+1,然后做“取整数计算”,当i//120>0时,设置time.sleep(60)休息60秒然后i重置为0继续!
这里能否用类似的思路,取整数运算?
似乎可行,我只需要让每个区间的分钟数值,先变成0,1,2,3,然后再改为0,15,30,45即可。我如今习惯了可视化更好的表述,如下:
思路既然清晰,我就在群里说明了我的想法,期待大家的验证:“大家好,数据很多,过多的if判断和嵌套会降低性能,不妨尝试用取整数计算。比如2//15=0,再*15,结果就是0/15/30/45四段。”喜乐君
于是大家简化了上面的计算方法,如下:
看上去还不错!
3、对时间的处理
上面的结果虽然不错,但是很明显没有充分利用Tableau中的日期函数,所以我又提出了新的完善建议:
“可以使用datetrunc函数,一次性提取hour之前的日期,然后再加上后面的分钟计算,这样可以进一步提高计算效率。try~”喜乐君
于是又有了下面的更优雅的计算方法:
不过,我发现我没有说清楚我的想法,这不是我想要的。虽然可行,但是这个表达式把日期转化为字符串(str计算),然后又做了相加。对于日期而言,这样的计算不安全,也有些冗长。所以,我进一步说明了我的想法:“外面的datetime函数可以尝试用dateadd来实现计算,datetrunc的日期结果add 日期的分段结果”喜乐君
有必要我说明一下我的意思:datetrunc是裁断,因此hour后面的部分都默认为0;而分钟已经通过“取整运算”返回为0/15/30/45四个结果,二者使用dateadd函数相加,就相当于一个日期加上了分钟部分。所以就有了下面的优雅表达式:
至此,最早性能低下的if嵌套和字符串计算,就替换为了算数计算和日期计算,比较完美的解决了这个问题。
当然,这个表达式性能依然不高,因为每一行还是要做多次运算,才能返回一个结果,也许还有更好的办法,以后可以一起更新。
4、选择运算的基本方法
我写这篇文章的重点是,面对此类问题,如何选择计算?Henry说程序员有几个境界:能实现、性能好、代码短、艺术性。四者兼之,自然是上等佳选。从性能的角度应该如何思考呢?
根据个人的经验,提几个角度:A、选择计算方法时,布尔判断优先于算数计算,算数计算优先于(嵌套)逻辑判断。因此,当我只是区分小于30分钟和大于30分钟时,我用一个判断来解决,但是当我要切分四阶段时,我选择用算数计算,只有二者都不能解决时,才考虑复杂逻辑判断。处理逻辑问题,“没有if解决不了的,如果有就用两个”;但是这是迫不得已的选择。即便使用if函数,也优先考虑iif、isnul、ifnull这样的简化函数,再使用完整逻辑函数。B、优先使用“原生性函数”。上面我们尽可能使用Tableau自带的日期函数,而非优先考虑字符串函数,原生函数一般都能更好的简化表达式,提高性能。
C、聚合函数优先于行级别函数。行级别计算往往会导致性能问题,特别是每一行的计算都还要非常多次时。不过,所有的字符串函数、日期函数都是行级别函数,这个地方是没有简化空间的;更多适用于算数计算等地方。
如果还有加上一句话的话,“条条大路通罗马,但总有最近的一条路。”