Bagaimana saya bisa memfilter tabel dalam mode org

11

Misalnya, saya ingin memfilter tabel yang membuatnya memperlihatkan baris yang hanya berisi string "USA" di kolom 3 dan 4.

yuxuan
sumber

Jawaban:

19

Anda dapat menggunakan banyak solusi. Saya berasumsi Anda ingin menghasilkan tabel baru berdasarkan yang sudah ada. Ini melibatkan fungsionalitas babel di mana Anda mendefinisikan blok kode yang menghasilkan tabel baru. Blok kode dapat dalam banyak bahasa, dan Anda bahkan dapat menentukan blok kode seperti itu untuk digunakan setelahnya secara normal dalam rumus tabel.

Saya menunjukkan di sini hanya sebuah contoh menggunakan emacs lisp. Anda dapat menemukan lebih banyak contoh dalam koleksi contoh saya di 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 |

Sekarang kita mendefinisikan fungsi filter yang menghasilkan tabel baru dengan nilai yang diperlukan.

  • Saya membaca di tabel sebelumnya dengan menggunakan argumen : var tbl = table1 pada baris BEGIN.
  • Saya mendefinisikan nilai yang akan difilter dalam hal yang sama : penugasan var dengan menetapkan val = "USA"
  • Perhatikan bahwa saya menggunakan argumen : colnames di baris BEGIN untuk mempertahankan judul kolom.
  • Saya hanya memfilter kolom 4 dalam contoh ini, untuk kesederhanaan. Tapi itu sepele untuk diperpanjang. Jika Anda menginginkan solusi eksplisit, tanyakan saja.
  # + NAME: my-filter
  # + BEGIN_SRC elisp: var tbl = table1 val = "USA": colnames y
    (cl-loop untuk baris dalam tbl
          jika (sama dengan (baris ketiga))
          kumpulkan baris ke newtbl
          akhirnya kembalikan newtbl)
  # + END_SRC

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

Saya juga dapat menggunakan fungsi ini dengan sintaks CALL mode-org

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

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

Saya juga menunjukkan di sini pendekatan SQLite di mana saya menggunakan persyaratan asli Anda untuk memfilter semua baris yang berisi string baik dalam kolom 3 atau 4. Kelemahan minor dari pendekatan sqlite adalah bahwa kita memiliki beberapa kode boilerplate untuk dibaca di dalam tabel dan membuat DB SQLite.

  # + NAME: my-filter2
  # + BEGIN_SRC sqlite: db table1.sqlite: var tbl = table1 val = "USA": colnames ya
    drop table jika ada table1;
    buat table1 tabel (col1 VARCHAR, col2 INTEGER, col3 VARCHAR,
    col4 VARCHAR, col5 INTEGER);
    impor "$ tbl" table1
    pilih * dari table1 di mana col3 = '$ val' atau col4 = '$ val';
  # + END_SRC

  # + HASIL:
  | 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"): colnames y

  # + HASIL:
  | 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 |

Semoga saya memahami pertanyaan Anda dengan benar dan tautannya membantu Anda menemukan variasi solusi yang lain.

Dfeich
sumber
Solusi bagus Dengan sqlite dan gnuplot, banyak plot dari tabel sumber tunggal dapat dihasilkan dengan ekonomi yang bagus.
Pengguna Emacs
Terima kasih atas solusi hebatnya! BTW, di lingkungan saya, saya harus menghapus symbol-namefungsi untuk berhasil dalam solusi Emacs Lisp. Hanya untuk menyebutkan.
RUserPassingBy
Terima kasih. Saya hanya menyadari sekarang bahwa saya telah menyiapkan contoh asli saya dari sebuah tabel yang diproduksi langsung oleh blok src menggunakan nama negara sebagai simbol, sehingga filter itu sebenarnya diserahkan simbol dan bukan string. Sekarang sudah diperbaiki.
dfeich
0

Saya menggunakan q - Teks sebagai Data , dan 2 fungsi di library-of-babel( Contoh-Contoh ) saya untuk menyediakan antarmuka mudah untuk query / bergabung dengan tabel org-inline dan .*svfile eksternal .

Di bawah tenda, q(melalui ) juga menggunakan , seperti pendekatan kedua dari @dfeich, tetapi menghilangkan kebutuhan untuk kode boilerplate berisik yang spesifik untuk setiap tabel sumber individu. Itu hanya perlu diinstal sekali melalui manajer paket sistem, biasanya di python-q-text-as-data.

Setelah pustaka babel Anda dimuat dengan 2 fungsi di bawah ini, Anda hanya perlu #+Call:seperti di bawah ini di file org Anda untuk menggunakan query SQL.

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

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

Ini membangun seperti baris perintah SELECT $select FROM $from WHERE $where, dengan default untuk parameter untuk memilih semua kolom dari stdinuntuk output.

Blok kode yang akan ditambahkan ke perpustakaan Anda adalah:

** 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
sumber