IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]用lisp在emacs org table中进行电子表格计算

    sheismylife发表于 2015-05-03 16:33:52
    love 0

    一句话,计算方面绝对比excel计算功能强。图形方面我还没有用过。对于编程者来讲,用鼠标拖拽操作还是用lisp编写计算公式哪个更符合思考的习惯,我觉得是后者。我这里只介绍lisp计算公式,如果关注简单的Calc计算公式,可以参考官方文档。


    如何引用表格中其他字段

    推荐写法,@row_index$col_index

    可以用C-c } 显示或者隐藏row_index和col_index

    比如:



    如何插入公式

    首先将光标定位到要计算的cell,然后可以通过菜单,tbl->calculat->set column formular, 也可以使用组合键: C-u C-c =

    然后在mini buffer中输入公式,回车。结果会在表格下面出现公式:

    * 测试表格
    
    #+CAPTION: DAU统计
    | 日期   | 新增  | 日活  | VV    |
    |--------+-------+-------+-------|
    | <6>    |   |   |   |
    | /      | <     | >     |       |
    | 2015-05-01 | 10    | 20    | 51    |
    | 2015-05-04 | 11    | 22    | 68    |
    |        |       |       |  119  |
    #+TBLFM: @6$4='(+ @4$4 @5$4);N
    

    注意,这里采用了lisp计算公式,前面要用单引号防止过早求值,后面需要加上;N,据说是N模式,我目前还不是很理解这个模式。


    如何重新计算

    C-u C-c * 可以对整个表格重新计算(光标必须停留在表格上), 结果如下:

    #+CAPTION: DAU统计
    | 日期   | 新增  | 日活  | VV    |
    |--------+-------+-------+-------|
    | <6>    |   |   |   |
    | /      | <     | >     |       |
    | 2015-05-01 | 10    | 20    | 50    |
    | 2015-05-04 | 11    | 22    | 68    |
    |        |       |       | 118   |
    #+TBLFM: @6$4='(+ @4$4 @5$4);N
    



    如何对某列求和

    有一种不需要编写公式就可以对某列求和的方式,将光标定位到某个cell,然后按下C-c + ,就会看到mini buffer的提示,然后按下S-Insert 键,就自动出现了求和的值。比如:

    #+CAPTION: DAU统计
    | 日期   | 新增  | 日活  | VV    |
    |--------+-------+-------+-------|
    | <6>    |   |   |   |
    | /      | <     | >     |       |
    | 2015-05-01 | 10    | 20    | 50    |
    | 2015-05-04 | 11    | 22    | 68    |
    |        |     21  |   42    |    118   |

    但是我还是觉得用lisp公式比较好,便于维护,因为一旦数据发生了变动,只需要重新计算一次表格即可。

    #+CAPTION: DAU统计
    | 日期   | 新增  | 日活  | VV    |
    |--------+-------+-------+-------|
    | <6>    |   |   |   |
    | /      | <     | >     |       |
    | 2015-05-01 | 10    | 20    | 49    |
    | 2015-05-04 | 11    | 22    | 68    |
    |        | 21    | 42    | 117   |
    #+TBLFM: @6$2='(+ @4$2..@5$2);N::@6$3='(+ @4$3..@5$3);N::@6$4='(+ @4$4..@5$4);N

    首先,这里有三个计算公式,中间使用::分隔开来

    然后引用范围的fields值可以用..表示from..to的语义。

    最后,每次修改任何一个值,直接重新计算该表即可。这个方式比较好。


    上面的公式还可以优化,可以使用相对位置指定最后一行:

    #+CAPTION: DAU统计
    |   日期 | 新增  | 日活  | VV    | 转化率 |
    |--------+-------+-------+-------+--------|
    |    <6> |   |   |   |        |
    |      / | <     | >     |       |        |
    | 2015-05-01 | 11    | 20    | 42    |        |
    | 2015-05-04 | 12    | 20    | 61    |        |
    | 2015-05-05 | 19    | 19    | 80    |        |
    |        | 42    | 59    | 183   |        |
    #+TBLFM: @7$2='(+ @4$2..@-1$2);N::@7$3='(+ @4$3..@-1$3);N::@7$4='(+ @4$4..@-1$4);N

    -1 表示在@7的前一行,因此可以在中间插入任意多行,公式只需要修改@7为正确行数,就能够正确计算。

    除法

    elisp的除法就是/, 当出线浮点数就作为浮点除法,如果都是整数,就整除。

    #+CAPTION: DAU统计
    |   日期 | 新增 | 日活 |    VV |             转化率 |
    |--------+------+------+-------+--------------------|
    |    <6> |      |      |       |                    |
    |      / |    < |    > |       |                    |
    | 2015-05-01 |   11 |   20 |    42 |                    |
    | 2015-05-04 |   11 |   20 |    41 |                    |
    | 2015-05-05 |   22 |   40 |    84 |                    |
    | 2015-05-06 |   41 |   81 |  68.0 |                    |
    |    All |   85 |  161 | 235.0 | 1.4596273291925466 |
    #+TBLFM: @8$2='(+ @4$2..@-1$2);N::@8$3='(+ @4$3..@-1$3);N::@8$4='(+ @4$4..@-1$4);N::@8$5='(/ @8$4 @8$3);N
    


    现在开始计算美一行的转化率:

    #+CAPTION: DAU统计
    |   日期 | 新增 |  日活 |    VV |             转化率 |
    |--------+------+-------+-------+--------------------|
    |    <6> |      |       |       |                    |
    |      / |    < |     > |       |                    |
    | 2015-05-01 |   11 |    20 |  42.0 |                2.1 |
    | 2015-05-04 |   12 |    20 |    41 |                  2 |
    | 2015-05-05 |   22 |  41.0 |  79.0 | 1.9268292682926829 |
    | 2015-05-06 |   41 |    81 |  68.0 | 0.8395061728395061 |
    |    All |   86 | 162.0 | 230.0 | 1.4197530864197532 |
    #+TBLFM: @4$5='(/ $4 $3);N::@5$5='(/ $4 $3);N::@6$5='(/ $4 $3);N::@7$5='(/ $4 $3);N::@8$2='(+ @4$2..@-1$2);N::@8$3='(+ @4$3..@-1$3);N::@8$4='(+ @4$4..@-1$4);N::@8$5='(/ $4 $3);N
    


    注意,这里写法再次优化:

    每个公式都有当前行的概念,比如

    @4$5='(/ $4 $3);N
    由于@4已经指定了当前行数,所以后面$4和$3就不需要指定行号,直接用当前行即可。


    管理多个公式

    公式一旦多起来,就需要工具帮忙管理。org tablei已经提供了。将光标停留在某个有公式的字段,然后按C-c ' ,就会出现新的buffer。



    移动右边buffer的光标,左边buffer会自动切换,反之亦然。而且右边的buffer将公式自动换行了。十分方便。




沪ICP备19023445号-2号
友情链接