I want to create a list how many times one tag use. It will make me decide which one to put in org-tag-persistent-alist

The data used can be obtained from org-agenda-files or a specified file. Is there any emacs function to do that? Thank you very much.

2 Answers 2


I use the following chunk of elisp to create a dynamic block containing a table where each row is a tag and number of use of that tag in the file. Add the block to your org file and hit C-c C-c to expand it:

#+BEGIN: tagblock

If you only want to count certain tags you can add a :tags option to the block and to add a label to the resulting table use :label

#+BEGIN: tagblock :tags ("tag1" "tag2" "tag3") :label tag-counts
| tag1 | 2 |
| tag2 | 4 |
| tag3 | 8 |

With the :todo option, only entries with a todo state (either any or in a list you specify) will be counted.

All the real work is done by the function org-freq-count which takes a parameterized search string (the same as an agenda tags search) and replaces %s in the search with each element of targets, counting the number of matches. If cmp is given, it will be used as a comparison function when sorting the output. This code requires the external packages dash and s, which can be installed from the MELPA repository

(require 'dash)
(require 's)

(defun org-freq-count (search targets &optional cmp)
  (let ((cmp (if (functionp cmp)
               (lambda (a b) nil))))

    (mapcar (lambda (x)
              (list x (length (org-map-entries t (format search x) nil))))
              (-filter #'stringp targets))

(defun org--tagblock-all-tags ()
  (-filter #'stringp (-map #'car (append

(defun org-write-freq-count (search targets name)
  (insert (s-concat
           (if name (insert (format "#+NAME: %s\n" name)))
            (lambda (x) (format "| %s | %s |" (nth 0 x) (nth 1 x)))
            (org-freq-count search targets)

(defun org-dblock-write:tagblock (params)
  (let ((todo (plist-get params :todo))
        (tags (or (plist-get params :tags) (org--tagblock-all-tags)))
        (label (plist-get params :label))
        (caption (plist-get params :caption))
    (when caption (insert (format "#+CAPTION: %s\n" caption)))
    (org-write-freq-count (cond ((equal todo t)
                                 (format "%%s/%s" (mapconcat 'identity
                                ((listp todo)
                                 (format "%%s/%s" (mapconcat 'identity
                                (t "%s"))
  • Very thoughtful answer. Thank you.
    – jagrg
    Commented Apr 16, 2020 at 1:09
  • Very nice answer indeed. One minor point: you probably should mention that the code requires dash.el and s.el.
    – NickD
    Commented Apr 16, 2020 at 2:09

You can also pass the results to R (or some other program) to do the calculations.

#+name: tags
#+begin_src emacs-lisp
(let (tags)
   (lambda ()
     (dolist (tag (org-get-tags))
       (push (list tag) tags))))

#+begin_src R :var tags=tags
sort(table(tags), decreasing=TRUE)

| work     | 3 |
| home     | 2 |
| noexport | 1 |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.