原文Org tutorial on table lookup functions, 由 Jarmo Hurri 编辑,维护。本文只做学习之用。
序言
Org
提供三个不同的函数,用于在表中执行搜索和数据依赖的计算。
这些函数可以用于实现数组关联,统计匹配单元格,结果排名或分组数据。
以下示例将有助于开始使用这些功能。
<!– more –>
具有唯一键的关联数组
查找最直接的用法是将 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
。
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)