Org-mode也有Excel一样的LOOKUP

原文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)

假定 PREDICATEnil ,在这种情况下使用默认谓词(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 来执行匹配。 注意, VALS 按照它们在 org-lookup-last 的签名中的顺序被分配给谓词,其中 VALS-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用户熟悉的以下电子表格操作都可以使用它们来实现: HLOOKUPVLOOKUPCOUNTIFSUMIFFREQUENCY

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容