清理和格式化文字
如何使用自訂運算式來清理不一致、非結構化或空白的文字。
假設 Metabase 想要為我們可愛的社群舉辦一場晚宴。主菜方面,我們有牛肉提比斯或鷹嘴豆燉菜可供選擇,配菜方面,我們有英吉拉或烤蔬菜。我們已發送包含菜單選項的調查,讓大家可以告訴我們他們想吃什麼。
不幸的是,我們忘記在表單上設定資料驗證,因此收到的回覆看起來像這樣
| Response ID | Main | Side |
|-------------|-------------------------------------|-------------------------|
| 1 | beef tibs | injera |
| 2 | chickpea stew | grilled vegetables |
| 3 | BEEF TIBS WITH CHICKPEA STEW PLEASE | |
| 4 | | Grilled Vegetables |
| 5 | Surprise me. | |
我們想要
- 清理並合併主菜和配菜值,以便我們可以計算最受歡迎的餐點。
- 處理以某種方式無效的回覆(例如多個主菜,或菜單上不存在的主菜)。
- 追蹤提交資訊遺漏回覆的客人。
總體而言,我們希望最終得到一個看起來像這樣的表格(向右捲動以檢視完整表格)
| 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 only | yes |
| 4 | | Grilled Vegetables | grilled vegetables only | yes |
| 5 | Surprise me. | | | yes |
搜尋和擷取文字
假設唯一有效的主菜選項是牛肉提比斯和鷹嘴豆燉菜。我們可以使用 regexextract
函數來檢查每個回覆中是否有有效的菜單選項。
若要在主菜欄中搜尋「beef tibs」值,我們將使用 regex 模式 (?i)(beef tibs)
建立自訂欄。此 regex 模式會執行不區分大小寫的檢查,以查看「beef tibs」是否出現在回覆中的任何位置。
使用下列項目建立 Beef 自訂欄
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. | |
然後,我們想要在主菜欄中搜尋有效值「chickpea stew」。
建立 Chickpea 欄
regexextract([Main], "(?i)(chickpea stew)")
以及輸出
| Response ID | Main | Chickpea |
|-------------|-------------------------------------|---------------|
| 1 | beef tibs | |
| 2 | chickpea stew | chickpea stew |
| 3 | BEEF TIBS WITH CHICKPEA STEW PLEASE | CHICKPEA STEW |
| 4 | | |
| 5 | Surprise me. | |
合併不同欄中的值
接下來,我們將建立一個名為 Main (Clean) 的欄,它將合併每位客人的回覆的有效主菜。我們想要設定一些邏輯,以便在 Main 包含下列項目時
- 單一有效選項(牛肉提比斯或鷹嘴豆燉菜),然後以該選項填寫 Main (Clean)。
- 多個有效選項,然後將第一個(最左邊)有效選項放入 Main (Clean)。
- 沒有有效選項,然後以空白值(空字串)填寫 Main (Clean)。
若要建立 Main (Clean),我們將使用 coalesce
函數來處理上面列出的三種情況,並將整個內容包裝在 lower
函數中,以將所有內容標準化為小寫。
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 WITH CHICKPEA STEW PLEASE | BEEF TIBS | CHICKPEA STEW | beef tibs |
| 4 | | | | |
| 5 | Surprise me. | | | |
擷取文字並合併結果
我們將以與主菜欄相同的方式處理配菜欄。首先,使用 regexextract
函數來搜尋並傳回配菜欄中的有效值。
建立 Injera 自訂欄
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 (Clean) 自訂欄
lower(coalesce([Injera],[Vegetables], ""))
以取得
| Response ID | Side | Injera | Vegetables | Side (Clean) |
|-------------|--------------------|--------|--------------------|--------------------|
| 1 | injera | injera | | injera |
| 2 | grilled vegetables | | grilled vegetables | grilled vegetables |
| 3 | | | | |
| 4 | Grilled Vegetables | | Grilled Vegetables | grilled vegetables |
| 5 | | | | |
合併不同欄中的值
最後,我們想要透過檢查每個情境來產生完整訂單
- 如果 Main (Clean) 和 Side (Clean) 都包含有效選項,則傳回「主菜加配菜」。
- 如果只有一個有效選項,則傳回「僅主菜」或「僅配菜」。
- 如果沒有有效選項,請將訂單留白(傳回空字串)。
若要檢查欄是否為非空白,我們將使用 isempty
函數。
例如,若要檢查 Main (Clean) 是否為空白
isempty([Main (Clean)])
若要檢查 Main (Clean) 和 Side (Clean) 是否都為空白,您可以使用 AND
來合併運算式
isempty([Main (Clean)]) AND isempty([Side (Clean)])
isempty
目前僅在另一個函數內運作,因此我們需要將我們的每個檢查放入 case
函數中。我們將把預留位置文字作為目前的輸出
case(
(isempty([Main (Clean)]) AND isempty([Side (Clean)])), "",
isempty([Side (Clean)]), "main only",
isempty([Main (Clean)]), "side only",
"main with side"
)
請注意,案例的順序很重要,因為
case
函數會依序評估每個運算式,並在找到第一個有效案例時停止。- 如果您將第一個案例與第二個案例交換,則運算式會確認 Side (Clean) 為空白,並立即傳回「僅主菜」,而不會檢查 Main (Clean) 是否也為空白。
最後,若要填寫每位客人的最終訂單,我們將使用 concat
函數來連結 Main (Clean) 和 Side (Clean) 中的值與其他字詞(包括空格)。
使用下列項目建立 Order 欄
case(
(isempty([Main (Clean)]) AND isempty([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 WITH CHICKPEA STEW PLEASE | | beef tibs | | beef tibs only |
| 4 | | Grilled Vegetables | | grilled vegetables | grilled vegetables only |
| 5 | Surprise me. | | | | |
標記具有空白值的列
假設我們想要新增一個名為 Follow up? 的欄,以追蹤遺漏有效主菜、配菜或兩者的訂單。這表示我們需要檢查 Order、Main (Clean) 或 Side (Clean) 中是否有任何欄為空白。
我們可以將 isempty
函數與 OR
運算子結合使用,以便在三個欄中的任何一個欄為空白時傳回「是」,而在所有欄都填寫有效資料時傳回「否」。
使用下列項目建立 Follow up?
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. | | | yes |
最佳實務與提示
在本教學課程中,每次我們需要擷取、合併或標記文字資料時,都會建立新的自訂欄。我們也將較簡單的函數(例如 lower
和 isempty
)與其他函數結合使用。一般而言,我們建議每次在使用具有多個參數的函數(例如 case
、regexextract
和 coalesce
)時,都建立新的自訂欄,因為
- 您可以確認您的運算式是否如預期般運作。
- 邏輯更容易閱讀和更新。
而且,如果您習慣使用其他工具(例如 SQL、試算表或 Python)中的函數,請查看自訂運算式文件中的相關函數章節。例如,您可以瞭解如何使用 case
的相關函數將 if-then 邏輯轉換為 Metabase 運算式。