自定义表达式
何时使用自定义表达式以及为何应在 Metabase 的笔记本编辑器中利用它们。
在数学中,表达式是符号的集合,它们共同表达一个值。如果您以前使用过电子表格软件,表达式就是公式,例如 =SUM(A1, B1)
。
Metabase **查询构建器**中的自定义表达式是强大的工具,可以在无需使用 SQL 的情况下满足绝大多数分析用例。事实上,使用查询构建器有很多 SQL 不具备的优势。
- 可扩展性:使用 **查询构建器** 构建查询可以让人们在无需了解任何 SQL 的情况下学习和构建您的问题。
- 钻取 允许人们按类别分解记录、放大、钻取到未聚合的记录,或点击查看数据。使用 Metabase 查询构建器构建的问题将为用户提供钻取的全部功能,但使用 SQL 构建的问题将只显示有限的选项,例如按值过滤。
而且您可以在开发过程中的任何时候通过将现有问题转换为原生 SQL 问题来切换到 SQL。
在 **查询构建器** 中有三个地方可以使用自定义表达式
- 自定义列 使用函数计算值(例如
+
用于相加数字)或操作文本(例如lower
用于将文本转换为小写)。 - 自定义过滤器 使用诸如
contains
等函数,这些函数的结果为真或假。 - 自定义汇总 使用诸如
count
或sum
等函数来聚合记录。
自定义列
我们可以使用表达式向数据添加自定义列来计算新列。让我们看看表达式的作用。这是 Metabase 附带的示例数据库中的 **订单** 表。
假设我们想知道订单根据税前小计应用的折扣百分比。例如,如果我们在 10 美元的订单上提供 1 美元的折扣,我们希望看到一列显示我们对该订单打了 10% 的折扣。
不幸的是,快速浏览预览中的列告诉我们数据库不存储该计算(即没有“折扣百分比”列)。我们只有订单的小计和折扣总额。
然而,多亏了数学,我们可以使用折扣总额和订单小计来计算百分比。这就是表达式发挥作用的地方:我们可以使用表达式计算每一行的折扣百分比,并将该计算值存储在新列中。
让我们来看看如何创建一个自定义列。
在 **查询构建器** 中,我们选择 **数据部分** 中的 **自定义列**。
要计算折扣百分比,我们需要将折扣除以原始总额(Subtotal
)以获得折扣百分比。
在表达式中,我们使用方括号引用列。例如,我们可以将“订单”表中的“折扣”列引用为 [Discount]
。如果我们需要引用通过外键链接的另一个表中的列,我们可以在表和列之间使用 .
,例如 [Table.Column]
(或者,您可以在输入左方括号 ([
) 时从出现的下拉菜单中选择 [Table → Column]
)。例如,我们可以输入 [Products.Category]
,它将解析为:[Products → Category]
)。
目前,我们只对“订单”表中的列感兴趣,因此无需引用另一个表。以下是我们将用于计算自定义折扣百分比列的表达式(或公式):
[Discount] / [Subtotal]
在 **表达式** 字段中输入该表达式,然后为新列命名:Discount percentage
。
点击“完成”,然后点击“可视化”按钮查看新列。
由于我们新创建的 Discount percentage
列的值与折扣有关,所以我们把这一列移到 Discount
列的旁边。您可以通过点击列标题并拖动列到目标位置来移动表格中的列,如下所示:
因为我们正在计算百分比,所以让我们调整格式使其更易读。点击 Discount percentage
标题以调出该列的 **操作菜单**,然后点击 **齿轮图标** 来格式化该列。
Metabase 将滑出具有选项的 **格式化侧边栏**。让我们将样式更改为 **百分比**,并将小数位数增加到 **2**。由于标题 Discount percentage
占用了大量空间,我们将其重命名为 Discount %
。
还有一个选项可以添加 **迷你条形图**。此条形图不会显示相对于 100% 的百分比;相反,迷你条形图将显示相对于其他订单所给折扣百分比的折扣百分比。现在我们先不添加迷你条形图。
这是添加了 Discount %
列的最终问题
自定义过滤器
Metabase 提供大量开箱即用的筛选选项,但您可以使用自定义筛选表达式设计更复杂的筛选器。这些对于创建使用 OR
语句的筛选器特别有用,这也是我们在这里要介绍的内容。
通常在查询构建器中,当我们向问题添加多个过滤器时,Metabase 会隐式地使用 AND
运算符组合这些过滤器。例如,如果我们添加一个以 Enormous
开头的产品过滤器和一个以 Computer
结尾的产品过滤器,我们的问题将只返回既以 Enormous
开头又以 Computer
结尾的产品,而 Metabase 示例数据库中不存在这样的产品。
要筛选以 Enormous
开头或以 Computer
结尾的产品,我们将从 **筛选器** 下拉菜单中选择 **自定义表达式**,并使用 startsWith
和 endsWith
函数。
startsWith(string1, string2)
endsWith(string1, string2)
函数 startsWith
和 endsWith
检查 string1
是否以 string2
开头/结尾。所以 string1
是要检查的字符串(大海捞针),而 string2
是要查找的文本(针)。由于我们要查找以 Enormous
开头或以 Computer
结尾的产品,我们可以使用 startsWith
和 endsWith
表达式,中间加上 OR 运算符。
startsWith([Title], "Enormous") OR endsWith([Title], "Computer")
生成的数据集将包含以 Enormous
开头或以 Computer
结尾的产品
请注意,自定义筛选表达式必须始终解析为真或假。但是,您可以在语句中嵌套不解析为真或假的表达式,例如
contains(concat([First Name], [Last Name]), "Wizard")
因为最外层函数(contains
)解析为真或假。而您不能将 concat([First Name], [Last Name])
用作过滤器,因为它会解析为文本字符串(尽管您可以使用 concat 创建一个自定义列,如 Full Name
)。
自定义汇总
自定义表达式解锁了许多不同的数据聚合方式。让我们考虑 Share
函数,它以小数形式返回匹配条件的行所占的百分比。例如,假设我们想知道产品线中纸制品所占的总百分比,即我们的产品线中纸制品所占的份额是多少?
首先,我们从示例数据库中选择 **产品** 表。接下来,我们点击查询构建器中的 **汇总** 按钮并选择 **自定义表达式**。然后,我们从下拉菜单中选择 Share
,这将提示我们输入一个条件。在这种情况下,我们想知道哪些产品的标题中包含“Paper”,因此我们将使用 contains
函数在 Title
中进行搜索。
Share(contains([Title], "Paper"))
然后我们命名我们的表达式(例如,Percentage of paper products
),然后点击 **完成**。点击 **可视化** 按钮,Metabase 将计算纸制品的份额。
要更改格式,请选择左下角的 **设置按钮** 以调出 **设置侧边栏**,并将 **数字选项 → 样式** 更改为 **百分比**。
整合起来
让我们用表达式创建一个相当复杂(人为构造)的问题。假设我们的任务是找出 2019 年每月羊毛和棉花产品的平均净流入,其中净流入是销售价格减去我们为产品支付的成本。换句话说:对于 2019 年每月销售的每单位羊毛和棉花产品,我们平均赚了(或赔了)多少钱?
为了得到这些迷人的数字,我们需要使用表达式来
- 计算每单位的销售价格(自定义列)。
- 过滤结果以仅包含羊毛或棉花产品(自定义过滤器),并将这些结果限制在 2019 年。
- 计算平均净流入(自定义汇总),并按月份分组。
我们开始吧
-
我们创建一个名为
Unit price
的自定义列。为了计算Unit price
,我们将使用表达式将小计除以销售单位数 (Quantity
)。[Subtotal] / [Quantity]
-
接下来,我们将使用自定义过滤器表达式来筛选
Wool
和Cotton
产品的订单(即,筛选Product.Title
中包含“Wool”或“Cotton”的产品订单)。contains([Products → Title], "Wool") OR contains([Products → Title], "Cotton")
-
我们还将筛选
01/01/2019
到12/31/2019
之间的订单。 -
我们将使用自定义表达式来创建自定义摘要。我们假设标准零售加价率为 50%(关键加价)。因此,如果
Product.Price
是 2 美元,我们假设每单位产品的获取成本是 1 美元。基于这个假设,我们可以简单地将每单位销售的净流入定义为Unit price
减去Product.Price
的一半。然后,我们将通过计算每个订单的这些数字的平均值来汇总这些数据。Average([Unit price] - [Products → Price] / 2)
-
最后,我们将这些订单按
Orders.Created_At
按月分组。
这是我们的笔记本
我们选择将数据可视化为折线图,我们可以点击它来钻取数据。
延伸阅读
- 文档:**查询构建器**中的自定义表达式。还有很多我们没有涵盖的表达式函数,请查阅文档获取完整函数列表。
- 时间序列比较 展示了如何使用自定义表达式来可视化和比较时间序列。
- 清理和格式化文本 使用自定义表达式处理混乱和缺失的数据。