Comment puis-je filtrer la table en mode org

11

Par exemple, je veux filtrer la table qui fait apparaître la ligne qui ne contient que la chaîne "USA" dans les colonnes 3 et 4.

yuxuan
la source

Réponses:

19

Vous pouvez utiliser une multitude de solutions. Je suppose que vous voulez produire une nouvelle table basée sur une table existante. Cela implique la fonctionnalité babel où vous définissez des blocs de code qui produisent la nouvelle table. Les blocs de code peuvent être dans de nombreuses langues, et vous pouvez même définir un tel bloc de code à utiliser ensuite normalement dans les formules de table.

Je montre ici juste un exemple utilisant emacs lisp. Vous pouvez trouver de nombreux autres exemples dans ma collection d'exemples sur 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 |

Nous définissons maintenant une fonction de filtre qui produit une nouvelle table avec les valeurs requises.

  • Je lis dans le tableau précédent en utilisant l' argument : var tbl = table1 dans la ligne BEGIN.
  • Je définis la valeur à filtrer de la même manière : affectation var en définissant val = "USA"
  • Notez que j'utilise l' argument : colnames dans la ligne BEGIN afin de conserver les en-têtes de colonne.
  • Je filtre uniquement la colonne 4 dans ces exemples, pour plus de simplicité. Mais il est trivial d'étendre. Si vous voulez la solution explicite, demandez simplement.
  # + NOM: mon-filtre
  # + BEGIN_SRC elisp: var tbl = table1 val = "USA": noms de col y
    (boucle en boucle pour ligne en tbl
          if (égal (nième 3 rang) val)
          recueillir la ligne dans newtbl
          enfin retourner newtbl)
  # + END_SRC

  # + RÉSULTATS: my-filter
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | row4 | 8 | JP | USA | 20 |
  | row8 | 16 | PL | USA | 40 |

Je peux également utiliser cette fonction avec la syntaxe CALL en mode org

  # + CALL: my-filter (tbl = table1, val = "CN"): noms de colonnes y

  # + RÉSULTATS:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | row1 | 2 | D | CN | 5 |
  | row7 | 14 | D | CN | 35 |

Je démontre également ici l'approche SQLite où j'utilise votre exigence d'origine de filtrer toutes les lignes qui contiennent la chaîne soit dans les colonnes 3 ou 4. Un inconvénient mineur de l'approche sqlite est que nous avons du code passe-partout à lire dans le tableau et à créer une base de données SQLite.

  # + NOM: mon-filtre2
  # + BEGIN_SRC sqlite: db table1.sqlite: var tbl = table1 val = "USA": noms de colonnes oui
    supprimer la table s'il existe table1;
    créer la table table1 (col1 VARCHAR, col2 INTEGER, col3 VARCHAR,
    col4 VARCHAR, col5 INTEGER);
    .import "$ tbl" table1
    sélectionnez * dans le tableau1 où col3 = '$ val' ou col4 = '$ val';
  # + END_SRC

  # + RÉSULTATS:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | row2 | 4 | USA | PL | 10 |
  | row4 | 8 | JP | USA | 20 |
  | row6 | 12 | USA | JP | 30 |
  | row8 | 16 | PL | USA | 40 |


  # + CALL: my-filter2 (tbl = table1, val = "CN"): noms de col y

  # + RÉSULTATS:
  | col1 | col2 | col3 | col4 | col5 |
  | ------ + ------ + ------ + ------ + ------ |
  | row1 | 2 | D | CN | 5 |
  | row3 | 6 | CN | D | 15 |
  | row7 | 14 | D | CN | 35 |
  | row9 | 18 | CN | D | 45 |

J'espère que j'ai bien compris votre question et que les liens vous aident à trouver d'autres variantes d'une solution.

dfeich
la source
Excellente solution. Avec sqlite et gnuplot, plusieurs tracés à partir d'une seule table source peuvent être générés avec une grande économie.
Emacs User
Merci pour la grande solution! BTW, dans mon environnement, j'ai dû supprimer une symbol-namefonction pour réussir dans la solution Emacs Lisp. Juste pour mention.
RUserPassingBy
Merci. Je ne réalisais que maintenant que j'avais préparé mon exemple original à partir d'un tableau produit directement par un bloc src en utilisant les noms de pays comme symboles, donc le filtre était en fait des symboles et non des chaînes. Il est maintenant corrigé.
dfeich
0

J'utilise q - Text as Data , et 2 fonctions dans mon library-of-babel( Conf-Example ) pour fournir une interface facile pour interroger / joindre des tables org-inline et des .*svfichiers externes .

Sous le capot, q(via ) utilise également , comme la deuxième approche de @dfeich, mais supprime le besoin de code passe-partout bruyant spécifique à chaque table source individuelle. Il ne doit être installé qu'une seule fois via le gestionnaire de packages système, généralement dans python-q-text-as-data.

Une fois que votre bibliothèque de babel est chargée avec les 2 fonctions ci-dessous, vous n'avez besoin que d'un #+Call:semblable ci-dessous dans votre fichier org pour utiliser les requêtes SQL.

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

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

Cela construit une ligne de commande comme SELECT $select FROM $from WHERE $where, avec des valeurs par défaut pour les paramètres pour sélectionner toutes les colonnes à partir stdinde la sortie.

Les blocs de code à ajouter à votre bibliothèque sont:

** 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
Alex Stragies
la source