3

I am using tables in org mode to track habits. There is a global table with each row as

| Date             | Habit1 | Habit2 | Habitn |
|                  | streak | streak | streak |
|------------------+--------+--------+--------|
| <2017-07-02 Sun> |      1 |      1 |     31 |
| <2017-07-03 Mon> |      2 |      2 |     32 |

Each habit column would specify no of days that I am successful at maintaining the habit(something like a winning streak). But it may be necessary to record additional information or notes about each habit.

For this I use separate detailed habit tables. As an example, consider habit of waking at 6:00 AM.

** Morning wake

| Date             | MW streak | MW time | No of hrs slept |
|------------------+-----------+---------+-----------------|
| <2017-07-02 Sun> |         1 |    6:00 | 7               |
| <2017-07-03 Mon> |         2 |    5:55 | 6               |

The problem with this is redundancy.
What would be optimal is to record data for each day under each habit table only, instead of recording data twice under each habit table and the global table.
Changes in column 2 of each habit table should then be reflected automatically in the global table.

While not exactly the same, this is somewhat similar to the foreign key concept in databases.
Is there any way to implement this?

1

One option is to use an org-babel source block in a language that has good support for database operations. Here is an example that uses the pandas library in Python.

* Merge of habit tracking tables
** Python source
Execute the following source block to re-generate the [[Global table]]

#+name: merge-tables-pandas
#+header: :var tab1=ew-tab :var tab2=aw-tab :var tab3=mw-tab
#+BEGIN_SRC python :colnames no :return rslt :output table
  import pandas as pd
  import numpy as np
  from functools import reduce
  # Read each table into a separate pandas dataframe
  dataframes = [pd.DataFrame(t[1:], columns=t[0], dtype='str')
                for t in [tab1, tab2, tab3]]
  # Merge all into a single dataframe
  df = reduce(lambda x, y: pd.merge(x, y, on='Date', how='outer'), dataframes)
  # Select for output only the date column plus the streak columns
  cols = ['Date'] + [c for c in df.columns if 'Streak' in c]
  # Extract only the columns we want, sorted by date, with missing
  # values converted back to empty string
  df = df[cols].sort_values(by='Date').fillna(value='')
  # Convert to list of lists, which org-babel will interpret as a table
  rslt = [df.columns.values.tolist(), None] + df.values.tolist()
#+END_SRC

** Global table
#+RESULTS: merge-tables-pandas
| Date             | EW Streak | AW Streak | MW Streak |
|------------------+-----------+-----------+-----------|
| <2017-07-02 Sun> |           |           |         1 |
| <2017-07-03 Mon> |         1 |           |         2 |
| <2017-07-04 Tue> |         2 |         1 |           |
| <2017-07-05 Wed> |           |         2 |           |
| <2017-07-06 Thu> |           |         3 |         1 |


** Evening Workouts
#+name: ew-tab
| Date             | EW Streak | EW duration | EW Type |
|------------------+-----------+-------------+---------|
| <2017-07-03 Mon> |         1 |        0:30 | Run     |
| <2017-07-04 Tue> |         2 |        1:15 | Swim    |

** Afternoon Workouts
#+name: aw-tab
| Date             | AW Streak | AW duration | AW Type |
|------------------+-----------+-------------+---------|
| <2017-07-04 Tue> |         1 |        2:30 | Cycle   |
| <2017-07-05 Wed> |         2 |        4:15 | Walk    |
| <2017-07-06 Thu> |         3 |        1:25 | Cycle   |

** Morning wake
#+name: mw-tab
| Date             | MW Streak | MW time | No of hrs slept |
|------------------+-----------+---------+-----------------|
| <2017-07-02 Sun> |         1 |    6:00 |               7 |
| <2017-07-03 Mon> |         2 |    5:55 |               6 |
| <2017-07-06 Thu> |         1 |    6:15 |               7 |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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