原文Org tutorial on table lookup functions, 由 Jarmo Hurri 編輯,維護。本文只做學習之用。
序言
Org
提供三個不同的函數,用于在表中執行搜索和數據依賴的計算。 這些函數可以用于實現數組關聯,統計匹配單元格,結果排名或分組數據。 以下示例將有助于開始使用這些功能。
具有唯一鍵的關聯數組
查找最直接的用法是將 Org
表的一部分視為關聯數組:一個鍵可用于查找相應的值。
假設你去斯堪的納維亞,并且想跟蹤你花了多少錢在旅途中。 你決定將所有金額轉換為歐元。 在行程之前,你請記下大致匯率,如下表所示:
#+TBLNAME: rates
| currency | abbreviation | euros |
|-----------------+--------------+-------|
| euro | eur | 1 |
| Norwegian krone | nok | 0.14 |
| Swedish krona | sek | 0.12 |
| US dollar | usd | 0.77 |
接下來將使用函數 org-lookup-first
和前面的匯率表格來自動將不同貨幣的金額轉換成歐元。 函數 org-lookup-first
的簽名如下:
(org-lookup-first VAL S-LIST R-LIST &optional PREDICATE)
假定 PREDICATE
為 nil
,在這種情況下使用默認謂詞(predicate) equal
, 則該函數將在 S-LIST
中搜索 VAL
的第一個實例,并從 R-LIST
中的相應位置返回一個值。 在下表中,每筆金額分配了貨幣縮寫; 對于相應的縮寫,在匯率表格的第二列中進行查找,然后從第三列返回相應的匯率。 對于每一行只需要填充前四列; 第5列和第6列自動計算產生。 請注意,如果找不到鍵值,則會出現錯誤:在最后一行中,空鍵將被搜索。
| date | expense | sum | currency | rate | euros |
|-------+------------------+------+----------+--------+--------|
| 1.3. | flights | 324 | eur | 1 | 324 |
| 4.6. | books and maps | 243 | usd | 0.77 | 187.11 |
| 30.7. | rental car | 8300 | sek | 0.12 | 996. |
| 2.7. | hotel | 1150 | sek | 0.12 | 138. |
| 2.7. | lunch | 190 | sek | 0.12 | 22.8 |
| 3.7. | fishing licenses | 1400 | nok | 0.14 | 196. |
| 3.7. | gasoline | 340 | | #ERROR | #ERROR |
#+TBLFM: $5='(org-lookup-first $4 '(remote(rates,@2$2..@>$2)) '(remote(rates,@2$3..@>$3)))::$6=$5*$3
多個匹配優先排序
教師的常見任務是從總分中分配考試成績。 這種分級的起點是具有等級邊界的表。 以下是一個這樣的表,其中行按照特定等級所需的下限的遞增排序。
#+TBLNAME: grade-boundaries
| lower bound | grade |
|-------------+-------|
| 0 | F |
| 10 | D |
| 20 | C |
| 30 | B |
| 40 | A |
使用函數 org-lookup-last
和根據前面的 等級邊界
表來為學生分配成績。 函數 org-lookup-last
的簽名與 org-lookup-first
的完全相同:
(org-lookup-last VAL S-LIST R-LIST &optional PREDICATE)
函數 org-lookup-last
會搜索 S-LIST
中的最后一個匹配項,并從 R-LIST
中的相應位置返回一個值。 用于分配等級的查找思想如下:假定學生的考試成績是33分。我們尋找學生的 marks 大于或等于下限的表中的最后一行; 在這種情況下,它是下邊界的行30。學生的成績是第二列的相應元素,在這種情況下是B.
因此,給定學生的標記數VAL,找到下限S滿足 (>= VAL S)
的表等級邊界的第一列的最后一行。 因此,我們將使用 >=
作為 PREDICATE
來執行匹配。 注意, VAL
和 S
按照它們在 org-lookup-last
的簽名中的順序被分配給謂詞,其中 VAL
在 S-LIST
之前。 下表列出了從總 marks 到最終成績的轉換。 注: 文字插值 L
表示表值的字面值插入到Elisp公式中,這是必須的,因為一些值是數字,一些是符號。
| student | marks | grade |
|---------+-------+-------|
| X | 30 | B |
| Y | 29 | C |
| Z | 5 | F |
| W | 55 | A |
#+TBLFM: $3='(org-lookup-last $2 '(remote(grade-boundaries,@2$1..@>$1)) '(remote(grade-boundaries,@2$2..@>$2)) '>=);L
統計匹配單元格
函數 org-lookup-all
不能在表等式中使用自己,因為它返回值列表。 但是,通過將函數與其他 elisp 函數相結合,可執行強大的查找任務。
作為一個簡單的例子,計算表中缺少值的數量。 函數 org-lookup-all
的簽名與其他兩個查找函數的簽名完全相同:
(org-lookup-all VAL S-LIST R-LIST &optional PREDICATE)
數搜索 S-LIST
中的所有匹配項,并從 R-LIST
中的相應位置返回所有相應的值。 與org-lookup-first和org-lookup-last的情況一樣,如果 R-LIST
為nil,則直接返回 S-LIST
相應匹配值。 注意使用 E
標志來保留范圍內的空字段。 還要注意,在這種情況下,以真正的二維范圍來進行查找,這也是可能的
| group | round 1 | round 2 |
|-------+---------+---------|
| A | | 2.4 |
| B | 4.7 | 11 |
| C | | |
| D | 5 | |
| E | | 7.2 |
| F | 3.2 | 4.3 |
| G | | 4.4 |
| H | | 8 |
|-------+---------+---------|
| total | missing | 7 |
#+TBLFM: @>$3='(length(org-lookup-all "" '(@2$2..@-1$3) nil));E
排序結果
org-lookup-all
的另一個示例應用是結果的自動排序。 在下表中,總數越大越好。 請注意,Elisp表達式還自動處理關聯關系。
| group | marks | rank |
|-------+-------+------|
| A | 22 | 2 |
| B | 22 | 2 |
| C | 14 | 4 |
| D | 28 | 1 |
| E | 9 | 5 |
#+TBLFM: $3='(+ 1 (length (org-lookup-all $2 '(@2$2..@>$2) nil '<)));N
統計原始數據的頻率
數據分析中的常見情況是對可視化的原始數據值進行分類(分組)。 通常是通過統計在特定范圍內的出現頻率來完成的。 可使用函數 org-lookup-all
,結合其他 elisp 函數來執行此任務。 此示例還顯示了如何使用表中的多個值構建更復雜的查找規則。
考慮下表,不同組A-I的不同結果。
#+TBLNAME: raw-data
| group | result |
|-------+--------|
| A | 2.3 |
| B | 4.2 |
| C | 1.1 |
| D | 3.6 |
| E | 4.5 |
| F | 2.4 |
| G | 1.0 |
| H | 2.3 |
| I | 2.8 |
將結果分為不同的,并且相斥的類。 例如,屬于第一類的值在區間 [1,1.9]
(包括端點)中。 為了執行這樣的分類,我們定義了以下兩參數謂詞函數 in-interval
。 請注意,此函數的第一個參數是一對,其第一個元素是下限,第二個成員是該間隔的上限。
#+BEGIN_SRC emacs-lisp
(defun in-interval (bounds el)
(and (>= el (car bounds)) (<= el (cadr bounds))))
#+END_SRC
#+RESULTS:
: in-interval
使用這個謂詞函數,我們可以構造一個具有分類邊界和相應頻率的表。 請注意,函數 org-lookup-all
的第一個參數是作為第一個參數傳遞給謂詞 in-interval
中的第一個參數,是一對邊界。
| lower bound | upper bound | frequency |
|-------------+-------------+-----------|
| 1 | 1.9 | 2 |
| 2 | 2.9 | 4 |
| 3 | 3.9 | 1 |
| 4 | 4.9 | 2 |
#+TBLFM: $3='(length (org-lookup-all '($1 $2) '(remote(raw-data,@2$2..@>$2)) nil 'in-interval));N
結論
Org 的 lookup
函數可用于大量不同的數據相關計算。 例如,libreoffice或Excel用戶熟悉的以下電子表格操作都可以使用它們來實現: HLOOKUP
, VLOOKUP
, COUNTIF
, SUMIF
和 FREQUENCY
。