Metabase学习教程:提问-7

204 阅读6分钟

清理和格式化文本

如何使用自定义的文本,清理非结构化或不一致的文本。

假设Metabase想为我们可爱的社区举办一个晚宴。对于主菜,我们有牛肉炖牛肉或鹰嘴豆炖菜,而对于两侧,我们有印度菜或烤蔬菜。我们已经发送了一份关于菜单选项的调查,这样每个人都可以告诉我们他们想吃什么。

不幸的是,我们忘记在表单上设置数据验证,因此响应如下所示:

Response ID | Main                                | Side                    |

|-------------|-------------------------------------|-------------------------|

| 1           | beef tibs                           | injera                  |

| 2           | chickpea stew                       | grilledvegetables      |

| 3           | BEEF TIBS WITHCHICKPEA STEW PLEASE |                        |

| 4           |                                     | GrilledVegetables      |

| 5          | Surprise me.                       |                         |

我们希望:

[if !supportLists]1.   [endif]整理并结合主食和副食,这样我们就可以数出最受欢迎的饭菜了。

[if !supportLists]2.   [endif]处理在某些方面无效的响应(例如多个电源,或者菜单上不存在的电源)。

[if !supportLists]3.   [endif]跟踪提交了缺少信息的回复的客人。

总的来说,我们希望最终得到一个如下所示的表(向右滚动可查看完整的表):

Response ID | Main                                | Side                    | Order                                 | Follow up? |

|-------------|-------------------------------------|-------------------------|---------------------------------------|------------|

| 1           | beef tibs                           | injera                  | beef tibs with injera                 | no         |

| 2           | chickpea stew                       | grilledvegetables      | chickpea stew withgrilled vegetables | no         |

| 3           | BEEF TIBS WITHCHICKPEA STEW PLEASE |                        | beef tibs only                       | yes        |

| 4           |                                     | GrilledVegetables      | grilled vegetablesonly               | yes        |

| 5          | Surprise me.                        |                         |                                       |yes        |

[if !supportLineBreakNewLine]

[endif]

搜索和提取文本

我们假设唯一有效的主要选择是牛肉和鹰嘴豆炖菜。我们可以使用regexextract 函数检查每个响应中的有效菜单选项。

在中搜索值“牛肉tibs”专栏,我们将创建一个自定义列使用regex模式 (?i)(beef

tibs)。此regex模式执行不区分大小写的检查,以查看“beef tibs”是否出现在响应中的任何位置。

创建牛肉自定义列使用:

regexextract([Main],

"(?i)(beef tibs)")

您应该得到输出:

| Response ID | Main                                | Beef      |

|-------------|-------------------------------------|-----------|

| 1           | beef tibs                           | beef tibs |

| 2           | chickpea stew                       |           |

| 3           | BEEF TIBS WITH CHICKPEA STEW PLEASE |BEEF TIBS |

| 4           |                                     |           |

| 5          | Surprise me.                       |           |

然后,我们要搜索有效值“鹰嘴豆炖菜”列。

创建鹰嘴豆列:

regexextract([Main],

"(?i)(chickpea stew)")

通过输出:

| Response ID | Main                                | Chickpea      |

|-------------|-------------------------------------|---------------|

| 1           | beef tibs                           |               |

| 2           | chickpea stew                       | chickpea stew |

| 3           | BEEF TIBS WITHCHICKPEA STEW PLEASE | CHICKPEA STEW |

| 4           |                                     |               |

| 5          | Surprise me.                        |               |


合并来自不同列的值

接下来,我们将创建一个名为主(干净) 这将合并每个客人的响应的有效干线。我们想建立一些逻辑如果包含:

一个有效的选择(牛肉或鹰嘴豆炖),然后填充主(干净) 有这个选择。

多个有效选项,然后将第一个(最左边)有效选项放入主(干净) .

没有有效选项,然后填充主(干净) 具有空值(空字符串)。

创造主(干净) ,我们将使用 功能来处理上面列出的三个案例,然后把整个事情包装成 功能以小写标准化所有内容。

lower(coalesce([Beef],[Chickpea],""))

这将给出输出(向右滚动可查看完整的表):

| Response ID | Main                                | Beef      | Chickpea      | Main (Clean)   |

|-------------|-------------------------------------|-----------|---------------|----------------|

| 1           | beef tibs                           | beef tibs |               | beef tibs      |

| 2           | chickpea stew                       |           | chickpea stew | chickpea stew  |

| 3           | BEEF TIBS WITHCHICKPEA STEW PLEASE | BEEF TIBS | CHICKPEA STEW | beef tibs      |

| 4           |                                     |           |               |                |

| 5          | Surprise me.                       |           |               |                |

我们来处理侧面列的方式与列。首先,使用regexextract 函数从中搜索并返回有效值side列。

regexextract([Side], "(?i)injera")

创建Vegetables 自定义列:

regexextract([Side],

"(?i)(grilled vegetables)")

要获得输出:

| Response ID | Side               |Injera | Vegetables         |

|-------------|--------------------|--------|--------------------|

| 1           | injera             | injera |                    |

| 2           | grilled vegetables|        | grilled vegetables |

| 3           |                    |        |                    |

| 4           | Grilled Vegetables|        | Grilled Vegetables |

| 5          |                    |        |                    |

然后,使用coalesce 函数lower函数要处理人们放置了部分、多个或没有有效side选项的情况,并将所有值转换为小写:

创建side clean 自定义列:

lower(coalesce([Injera],[Vegetables], ""))

得到

Response ID | Side               |Injera | Vegetables         | Side(Clean)       |

|-------------|--------------------|--------|--------------------|--------------------|

| 1           | injera             | injera |                    | injera             |

| 2           | grilled vegetables|        | grilled vegetables | grilledvegetables |

| 3           |                    |        |                    |                    |

| 4           | Grilled Vegetables|        | Grilled Vegetables | grilledvegetables |

| 5           |                    |        |                    |                    |

组合来自不同列的值

最后,我们希望通过检查每个场景来生成完整的订单:

如果主(干净)侧面(干净) 两者都包含一个有效的选项,然后返回“main

    with side”。

如果只有一个有效选项,则返回“main only”或“side

    only”。

如果没有有效的选项,请将订单留空(返回空字符串)。

要检查列是否为非空,我们将使用isempty函数.

例如,检查Main clean 为空:

isempty([Main

(Clean)])

检查是否Main clean Side clean 二者都blank,可以使用以及:

isempty([Main

(Clean)]) AND isempty([Side (Clean)])

isempty目前只在另一个函数中工作,所以我们需要把每一张支票放在case函数。我们暂时将占位符文本作为输出:

case(

(isempty([Main (Clean)]) ANDisempty([Side (Clean)])), "",

isempty([Side (Clean)]),"main only",

isempty([Main (Clean)]),"side only",

"main with side"

)

请注意,Case的顺序很重要,因为:

这个case函数按顺序计算每个表达式,并在第一找到有效案例。

如果将第一个大小写替换为第二个大小写,表达式将确认这一点side clean 为空并立即返回“main only”,而不必检查是否main clean 也是空的。

最后,为了填写每位客人的最终订单,我们将使用concat函数将值从main clean side clean 其他单词(包括空格)。

创建命令使用列:

case(

(isempty([Main (Clean)]) ANDisempty([Side (Clean)])), "",

isempty([Side (Clean)]),concat([Main (Clean)], " only"),

isempty([Main (Clean)]),concat([Side (Clean)], " only"),

concat([Main (Clean)], " with", [Side (Clean)])

)

总的来说,这将为我们提供一组如下格式的列(向右滚动可查看完整的表):

| Response ID | Main                                | Side               | Main (Clean)    | Side (Clean)       | Order                                 |

|-------------|-------------------------------------|--------------------|-----------------|--------------------|---------------------------------------|

| 1           | beef tibs                           | injera             | beef tibs       | injera             | beef tibs with injera                 |

| 2           | chickpea stew                       | grilled vegetables |chickpea stew   | grilled vegetables |chickpea stew with grilled vegetables |

| 3           | BEEF TIBS WITHCHICKPEA STEW PLEASE |                   | beef tibs       |                    | beef tibs only                        |

| 4           |                                     | GrilledVegetables |                 | grilledvegetables | grilled vegetables only               |

| 5          | Surprise me.                       |                    |                 |                    |                                       |

用空白值标记行

假设我们要添加一个名为跟进? 跟踪缺少有效主、一个边或两者的订单。这意味着我们需要检查OrderMain

(Clean), 或者 Side

(Clean) 是空白的。

我们可以把isempty功能或者 operator如果三列中的任何一列为空,则返回“yes”;如果所有列都用有效数据填充,则返回“no”。

创建跟进? 使用:

case(( isempty([Order])

OR isempty([Main (Clean)])

OR isempty([Side (Clean)])), "yes", "no")

最终结果(向右滚动可查看完整表格):

| Response ID | Main                                | Side                    | Order                                 | Follow up? |

|-------------|-------------------------------------|-------------------------|---------------------------------------|------------|

| 1           | beef tibs                           | injera                  | beef tibs with injera                 | no        |

| 2           | chickpea stew                       | grilled vegetables      | chickpea stew with grilled vegetables | no         |

| 3           | BEEF TIBS WITH CHICKPEA STEW PLEASE |                         | beef tibs                             | yes        |

| 4           |                                     | vegetables              | grilled vegetables                    | yes        |

| 5           | Surprise me.                        |                         |

最佳实践和技巧

在本教程中,每次需要提取、组合或标记文本数据时,我们都会创建一个新的自定义列。我们还结合了更简单的函数(例如lowerisempty)其他功能。通常,我们建议每次使用带有多个参数的函数时创建一个新的自定义列(例如case,regexextractcoalesce),因为:

您可以确认表达式是否按预期工作。

逻辑更容易阅读和更新。

如果您习惯于使用其他工具(如SQL、电子表格或Python)中的函数,请查看相关功能自定义表达式文档中的部分。例如,您可以学习如何使用case的相关函数.