如何在组织模式下过滤表


11

例如,我要过滤表格,使其在第3列和第4列中显示仅包含“ USA”字符串的行。

Answers:


19

您可以使用多种解决方案。我假设您想基于现有的表生成一个新表。这涉及babel功能,您可以在其中定义产生新表的代码块。代码块可以使用多种语言,甚至您可以定义一个这样的代码块,以便以后在表公式中正常使用。

我在这里仅显示一个使用emacs lisp的示例。您可以在github上的示例集中找到更多示例:https : //github.com/dfeich/org-babel-examples

 *table filter

  #+NAME: table1
  | col1  | col2 | col3 | col4 | col5 |
  |-------+------+------+------+------|
  | row0  |    0 | CH   | CH   |    0 |
  | row1  |    2 | D    | CN   |    5 |
  | row2  |    4 | USA  | PL   |   10 |
  | row3  |    6 | CN   | D    |   15 |
  | row4  |    8 | JP   | USA  |   20 |
  | row5  |   10 | PL   | PL   |   25 |
  | row6  |   12 | USA  | JP   |   30 |
  | row7  |   14 | D    | CN   |   35 |
  | row8  |   16 | PL   | USA  |   40 |
  | row9  |   18 | CN   | D    |   45 |
  | row10 |   20 | CH   | CH   |   50 |

现在,我们定义一个过滤器函数,该函数将生成具有所需值的新表。

  • 我正在使用BEGIN行中的:var tbl = table1参数来读取上一个表。
  • 我通过设置val =“ USA”来定义要在相同的:var分配中过滤的值
  • 请注意,我在BEGIN行中使用:colnames参数来保留列标题。
  • 为了简单起见,我仅在这些示例中过滤第4列。但是扩展是微不足道的。如果您需要明确的解决方案,只需询问。
  #+ NAME:我的过滤器
  #+ BEGIN_SRC elisp:var tbl = table1 val =“ USA”:colnames y
    (tbl中行的cl循环
          if(等于(第3行)val)
          收集行到newtbl
          最终返回newtbl)
  #+ END_SRC

  #+结果:my-filter
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | 第4行| 8 | JP | 美国| 20 |
  | 第8行| 16 | PL | 美国| 40 |

我也可以将此功能与org-mode CALL语法一起使用

  #+ CALL:my-filter(tbl = table1,val =“ CN”):名称y

  #+结果:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | 第1行| 2 | D | CN | 5 |
  | 第7行| 14 | D | CN | 35 |

我还将在这里演示SQLite方法,在该方法中,我将使用您最初的要求来过滤第3列或第4列中包含字符串的所有行。sqlite方法的一个小缺点是我们需要在表中读取一些样板代码并创建SQLite数据库。

  #+ NAME:my-filter2
  #+ BEGIN_SRC sqlite:db table1.sqlite:var tbl = table1 val =“ USA”:colnames yes
    如果存在table1,则删除表;
    创建表table1(col1 VARCHAR,col2 INTEGER,col3 VARCHAR,
    col4 VARCHAR,col5 INTEGER);
    .import“ $ tbl” table1
    从表1中选择*,其中col3 ='$ val'或col4 ='$ val';
  #+ END_SRC

  #+结果:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | 第2行| 4 | 美国| PL | 10 |
  | 第4行| 8 | JP | 美国| 20 |
  | 第6行| 12 | 美国| JP | 30 |
  | 第8行| 16 | PL | 美国| 40 |


  #+ CALL:my-filter2(tbl = table1,val =“ CN”):名称y

  #+结果:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | 第1行| 2 | D | CN | 5 |
  | 第3行| 6 | CN | D | 15 |
  | 第7行| 14 | D | CN | 35 |
  | 第9行| 18 | CN | D | 45 |

希望我能正确理解您的问题,并希望这些链接能帮助您找到解决方案的其他变化。


很好的解决方案。使用sqlite和gnuplot可以经济高效地从一个源表生成多个图。
Emacs用户

谢谢您的出色解决方案!顺便说一句,在我的环境中,我必须删除symbol-name功能才能在Emacs Lisp解决方案中成功。只是提一下。
RUserPassingBy

谢谢。我现在才意识到,我是使用src块直接使用国家名称作为符号从一个表直接生成的表中准备了原始示例,因此过滤器实际上是传递的符号,而不是字符串。现在已更正。
dfeich

0

我用q -文本作为数据,并且在我的2个功能library-of-babelCONF-实施例),以提供一种简单的接口的查询/加入ORG-直列表和外部.*sv文件。

在幕后,q(通过)还使用了,就像@dfeich中的第二种方法一样,但是消除了对每个单独的源表特定的嘈杂样板代码的需要。它只需要通过系统软件包管理器安装一次,通常在中python-q-text-as-data

一旦您的babel库加载了下面的2个函数,您只需#+Call:在组织文件中下面提供一个like即可使用SQL查询。

#+CALL: Q[:stdin table1](where="col4=='USA'")

#+RESULTS:
| col1 | col2 | col3 | col4 | col5 |
|------+------+------+------+------|
| row4 |    8 | JP   | USA  |   20 |
| row8 |   16 | PL   | USA  |   40 |

这样会构造一个类似的命令行SELECT $select FROM $from WHERE $where,默认使用参数作为参数以从中选择所有列以stdin进行输出。

要添加到库中的代码块是:

** Add a header Row to tables
#+name: addhdr
#+begin_src emacs-lisp :var tbl=""
(cons (car tbl) (cons 'hline (cdr tbl)))
#+end_src

** Filtering with SQL
#+NAME: Q
#+HEADER: :results value table
#+HEADER: :var callOptsStd="-H -O -t" callOpts=""
#+HEADER: :post addhdr(*this*)
#+BEGIN_SRC shell :stdin Ethers :var select="*" from="-" where="1"
q $callOptsStd $callOpts "Select $select from $from where $where"
#+END_SRC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.