Giter Club home page Giter Club logo

r-ledger's Introduction

ledger

CRAN Status Badge R-CMD-check Coverage Status RStudio CRAN mirror downloads

ledger is an R package to import data from plain text accounting software like Ledger, HLedger, and Beancount into an R data frame for convenient analysis, plotting, and export.

Right now it supports reading in the register from ledger, hledger, and beancount files.

To install the last version released to CRAN use the following command in R:

install.packages("ledger")

To install the development version of the ledger package (and its R package dependencies) use the install_github function from the remotes package in R:

install.packages("remotes")
remotes::install_github("trevorld/r-ledger")

This package also has some system dependencies that need to be installed depending on which plaintext accounting files you wish to read to be able to read in:

ledger
ledger (>= 3.1)
hledger
hledger (>= 1.4)
beancount
beancount (>= 2.0)

To install hledger run the following in your shell:

stack update && stack install --resolver=lts-14.3 hledger-lib-1.15.2 hledger-1.15.2 hledger-web-1.15 hledger-ui-1.15 --verbosity=error

To install beancount run the following in your shell:

pip3 install beancount

Several pre-compiled Ledger binaries are available (often found in several open source repos).

To run the unit tests you'll also need the suggested R package testthat.

The main function of this package is register which reads in the register of a plaintext accounting file. This package also registers S3 methods so one can use rio::import to read in a register, a net_worth convenience function, and a prune_coa convenience function.

Here are some examples of very basic files stored within the package:

library("ledger")
ledger_file <- system.file("extdata", "example.ledger", package = "ledger")
register(ledger_file)
## # A tibble: 42 × 8
##    date       mark  payee       description     account amount commodity comment
##    <date>     <chr> <chr>       <chr>           <chr>    <dbl> <chr>     <chr>
##  1 2015-12-31 *     <NA>        Opening Balanc… Assets…  5000  USD       ""
##  2 2015-12-31 *     <NA>        Opening Balanc… Equity… -5000  USD       ""
##  3 2016-01-01 *     Landlord    Rent            Assets… -1500  USD       ""
##  4 2016-01-01 *     Landlord    Rent            Expens…  1500  USD       ""
##  5 2016-01-01 *     Brokerage   Buy Stock       Assets… -1000  USD       ""
##  6 2016-01-01 *     Brokerage   Buy Stock       Equity…  1000  USD       ""
##  7 2016-01-01 *     Brokerage   Buy Stock       Assets…     4  SP        ""
##  8 2016-01-01 *     Brokerage   Buy Stock       Equity… -1000  USD       ""
##  9 2016-01-01 *     Supermarket Grocery store   Expens…   501. USD       "Link:…
## 10 2016-01-01 *     Supermarket Grocery store   Liabil…  -501. USD       "Link:…
## # ℹ 32 more rows
hledger_file <- system.file("extdata", "example.hledger", package = "ledger")
register(hledger_file)
## # A tibble: 42 × 12
##    date       mark  payee   description account amount commodity historical_cost
##    <date>     <chr> <chr>   <chr>       <chr>    <dbl> <chr>               <dbl>
##  1 2015-12-31 *     <NA>    Opening Ba… Assets…  5000  USD                 5000
##  2 2015-12-31 *     <NA>    Opening Ba… Equity… -5000  USD                -5000
##  3 2016-01-01 *     Landlo… Rent        Assets… -1500  USD                -1500
##  4 2016-01-01 *     Landlo… Rent        Expens…  1500  USD                 1500
##  5 2016-01-01 *     Broker… Buy Stock   Assets… -1000  USD                -1000
##  6 2016-01-01 *     Broker… Buy Stock   Equity…  1000  USD                 1000
##  7 2016-01-01 *     Broker… Buy Stock   Assets…     4  SP                  1000
##  8 2016-01-01 *     Broker… Buy Stock   Equity… -1000  USD                -1000
##  9 2016-01-01 *     Superm… Grocery st… Expens…   501. USD                  501.
## 10 2016-01-01 *     Superm… Grocery st… Liabil…  -501. USD                 -501.
## # ℹ 32 more rows
## # ℹ 4 more variables: hc_commodity <chr>, market_value <dbl>,
## #   mv_commodity <chr>, id <chr>
beancount_file <- system.file("extdata", "example.beancount", package = "ledger")
register(beancount_file)
## # A tibble: 42 × 13
##    date       mark  payee   description account amount commodity historical_cost
##    <date>     <chr> <chr>   <chr>       <chr>    <dbl> <chr>               <dbl>
##  1 2015-12-31 *     ""      Opening Ba… Assets…  5000  USD                 5000
##  2 2015-12-31 *     ""      Opening Ba… Equity… -5000  USD                -5000
##  3 2016-01-01 *     "Landl… Rent        Assets… -1500  USD                -1500
##  4 2016-01-01 *     "Landl… Rent        Expens…  1500  USD                 1500
##  5 2016-01-01 *     "Broke… Buy Stock   Assets… -1000  USD                -1000
##  6 2016-01-01 *     "Broke… Buy Stock   Equity…  1000  USD                 1000
##  7 2016-01-01 *     "Broke… Buy Stock   Assets…     4  SP                  1000
##  8 2016-01-01 *     "Broke… Buy Stock   Equity… -1000  USD                -1000
##  9 2016-01-01 *     "Super… Grocery st… Expens…   501. USD                  501.
## 10 2016-01-01 *     "Super… Grocery st… Liabil…  -501. USD                 -501.
## # ℹ 32 more rows
## # ℹ 5 more variables: hc_commodity <chr>, market_value <dbl>,
## #   mv_commodity <chr>, tags <chr>, id <chr>

Here is an example reading in a beancount file generated by bean-example:

bean_example_file <- tempfile(fileext = ".beancount")
system(paste("bean-example -o", bean_example_file), ignore.stderr=TRUE)
df <- register(bean_example_file)
print(df)
## # A tibble: 2,907 × 13
##    date       mark  payee  description account  amount commodity historical_cost
##    <date>     <chr> <chr>  <chr>       <chr>     <dbl> <chr>               <dbl>
##  1 2022-01-01 *     ""     Opening Ba… Assets…  3.78e3 USD                3783.
##  2 2022-01-01 *     ""     Opening Ba… Equity… -3.78e3 USD               -3783.
##  3 2022-01-01 *     ""     Allowed co… Income… -1.85e4 IRAUSD           -18500
##  4 2022-01-01 *     ""     Allowed co… Assets…  1.85e4 IRAUSD            18500
##  5 2022-01-04 *     "BANK… Monthly ba… Assets… -4   e0 USD                  -4
##  6 2022-01-04 *     "BANK… Monthly ba… Expens…  4   e0 USD                   4
##  7 2022-01-05 *     "Rive… Paying the… Assets… -2.4 e3 USD               -2400
##  8 2022-01-05 *     "Rive… Paying the… Expens…  2.4 e3 USD                2400
##  9 2022-01-05 *     "Jewe… Eating out  Liabil… -3.74e1 USD                 -37.4
## 10 2022-01-05 *     "Jewe… Eating out  Expens…  3.74e1 USD                  37.4
## # ℹ 2,897 more rows
## # ℹ 5 more variables: hc_commodity <chr>, market_value <dbl>,
## #   mv_commodity <chr>, tags <chr>, id <chr>
suppressPackageStartupMessages(library("dplyr"))
dplyr::filter(df, grepl("Expenses", account), grepl("trip", tags)) %>%
    group_by(trip = tags, account) %>%
    summarize(trip_total = sum(amount), .groups = "drop")
## # A tibble: 6 × 3
##   trip                  account                  trip_total
##   <chr>                 <chr>                         <dbl>
## 1 trip-los-angeles-2022 Expenses:Food:Alcohol          23.4
## 2 trip-los-angeles-2022 Expenses:Food:Coffee           41.9
## 3 trip-los-angeles-2022 Expenses:Food:Restaurant      613.
## 4 trip-los-angeles-2023 Expenses:Food:Alcohol          14.8
## 5 trip-los-angeles-2023 Expenses:Food:Coffee           12.8
## 6 trip-los-angeles-2023 Expenses:Food:Restaurant      739.

If one has loaded in the ledger package one can also use rio::import to read in the register:

df2 <- rio::import(bean_example_file)
all.equal(df, tibble::as_tibble(df2))
## [1] TRUE

The main advantage of this is that it allows one to use rio::convert to easily convert plaintext accounting files to several other file formats such as a csv file. Here is a shell example:

bean-example -o example.beancount
Rscript --default-packages=ledger,rio -e 'convert("example.beancount", "example.csv")'

Some examples of using the net_worth function using the example files from the register examples:

dates <- seq(as.Date("2016-01-01"), as.Date("2018-01-01"), by="years")
net_worth(ledger_file, dates)
## # A tibble: 3 × 6
##   date       commodity net_worth assets liabilities revalued
##   <date>     <chr>         <dbl>  <dbl>       <dbl>    <dbl>
## 1 2016-01-01 USD           5000    5000          0         0
## 2 2017-01-01 USD           4361.   4882       -521.        0
## 3 2018-01-01 USD           6743.   6264       -521.     1000
net_worth(hledger_file, dates)
## # A tibble: 3 × 5
##   date       commodity net_worth assets liabilities
##   <date>     <chr>         <dbl>  <dbl>       <dbl>
## 1 2016-01-01 USD           5000    5000          0
## 2 2017-01-01 USD           4361.   4882       -521.
## 3 2018-01-01 USD           6743.   7264       -521.
net_worth(beancount_file, dates)
## # A tibble: 3 × 5
##   date       commodity net_worth assets liabilities
##   <date>     <chr>         <dbl>  <dbl>       <dbl>
## 1 2016-01-01 USD           5000    5000          0
## 2 2017-01-01 USD           4361.   4882       -521.
## 3 2018-01-01 USD           6743.   7264       -521.
dates <- seq(min(as.Date(df$date)), max(as.Date(df$date)), by="years")
net_worth(bean_example_file, dates)
## # A tibble: 6 × 5
##   date       commodity net_worth assets liabilities
##   <date>     <chr>         <dbl>  <dbl>       <dbl>
## 1 2023-01-01 IRAUSD           0      0           0
## 2 2023-01-01 USD          38821. 40256       -1435.
## 3 2023-01-01 VACHR           26     26           0
## 4 2024-01-01 IRAUSD           0      0           0
## 5 2024-01-01 USD          83645. 85451.      -1806.
## 6 2024-01-01 VACHR           52     52           0

Some examples using the prune_coa function to simplify the "Chart of Account" names to a given maximum depth:

suppressPackageStartupMessages(library("dplyr"))
df <- register(bean_example_file) %>% dplyr::filter(!is.na(commodity))
df %>% prune_coa() %>%
    group_by(account, mv_commodity) %>%
    summarize(market_value = sum(market_value), .groups = "drop")
## # A tibble: 11 × 3
##    account     mv_commodity market_value
##    <chr>       <chr>               <dbl>
##  1 Assets      IRAUSD              6500
##  2 Assets      USD                99028.
##  3 Assets      VACHR                102
##  4 Equity      USD                -3783.
##  5 Expenses    IRAUSD             49000
##  6 Expenses    USD               224444.
##  7 Expenses    VACHR                208
##  8 Income      IRAUSD            -55500
##  9 Income      USD              -313541.
## 10 Income      VACHR               -310
## 11 Liabilities USD                -2382.
df %>% prune_coa(2) %>%
    group_by(account, mv_commodity) %>%
    summarize(market_value = sum(market_value), .groups = "drop")
## # A tibble: 17 × 3
##    account                     mv_commodity market_value
##    <chr>                       <chr>               <dbl>
##  1 Assets:US                   IRAUSD              6500
##  2 Assets:US                   USD                99028.
##  3 Assets:US                   VACHR                102
##  4 Equity:Opening-Balances     USD                -3783.
##  5 Expenses:Financial          USD                  438.
##  6 Expenses:Food               USD                17109.
##  7 Expenses:Health             USD                 6008.
##  8 Expenses:Home               USD                72865.
##  9 Expenses:Taxes              IRAUSD             49000
## 10 Expenses:Taxes              USD               124784.
## 11 Expenses:Transport          USD                 3240
## 12 Expenses:Vacation           VACHR                208
## 13 Income:US                   IRAUSD            -55500
## 14 Income:US                   USD              -313541.
## 15 Income:US                   VACHR               -310
## 16 Liabilities:AccountsPayable USD                    0
## 17 Liabilities:US              USD                -2382.

Here is some examples using the functions in the package to help generate various personal accounting reports of the beancount example generated by bean-example.

First we load the (mainly tidyverse) libraries we'll be using and adjusting terminal output:

library("ledger")
library("dplyr")
filter <- dplyr::filter
library("ggplot2")
library("scales")
library("tidyr")
library("zoo")
filename <- tempfile(fileext = ".beancount")
system(paste("bean-example -o", filename), ignore.stderr=TRUE)
df <- register(filename) %>% mutate(yearmon = zoo::as.yearmon(date)) %>%
      filter(commodity=="USD")
nw <- net_worth(filename)

Then we'll write some convenience functions we'll use over and over again:

print_tibble_rows <- function(df) {
    print(df, n=nrow(df))
}
count_beans <- function(df, filter_str = "", ...,
                        amount = "amount",
                        commodity="commodity",
                        cutoff=1e-3) {
    commodity <- sym(commodity)
    amount_var <- sym(amount)
    filter(df, grepl(filter_str, account)) %>%
        group_by(account, !!commodity, ...) %>%
        summarize(!!amount := sum(!!amount_var), .groups = "drop") %>%
        filter(abs(!!amount_var) > cutoff & !is.na(!!amount_var)) %>%
        arrange(desc(abs(!!amount_var)))
}

Here is some basic balance sheets (using the market value of our assets):

print_balance_sheet <- function(df) {
    assets <- count_beans(df, "^Assets",
                 amount="market_value", commodity="mv_commodity")
    print_tibble_rows(assets)
    liabilities <- count_beans(df, "^Liabilities",
                       amount="market_value", commodity="mv_commodity")
    print_tibble_rows(liabilities)
}
print(nw)
## # A tibble: 3 × 5
##   date       commodity net_worth  assets liabilities
##   <date>     <chr>         <dbl>   <dbl>       <dbl>
## 1 2024-05-19 IRAUSD        6500    6500           0
## 2 2024-05-19 USD         100688. 102388.      -1701.
## 3 2024-05-19 VACHR          110     110           0
print_balance_sheet(prune_coa(df, 2))
## # A tibble: 1 × 3
##   account   mv_commodity market_value
##   <chr>     <chr>               <dbl>
## 1 Assets:US USD                 2273.
## # A tibble: 1 × 3
##   account        mv_commodity market_value
##   <chr>          <chr>               <dbl>
## 1 Liabilities:US USD                -1701.
print_balance_sheet(df)
## # A tibble: 3 × 3
##   account                 mv_commodity market_value
##   <chr>                   <chr>               <dbl>
## 1 Assets:US:BofA:Checking USD              1857.
## 2 Assets:US:ETrade:Cash   USD               417.
## 3 Assets:US:Vanguard:Cash USD                -0.180
## # A tibble: 1 × 3
##   account                    mv_commodity market_value
##   <chr>                      <chr>               <dbl>
## 1 Liabilities:US:Chase:Slate USD                -1701.

Here is a basic chart of one's net worth from the beginning of the plaintext accounting file to today by month:

next_month <- function(date) {
    zoo::as.Date(zoo::as.yearmon(date) + 1/12)
}
nw_dates <- seq(next_month(min(df$date)), next_month(Sys.Date()), by="months")
df_nw <- net_worth(filename, nw_dates) %>% filter(commodity=="USD")
ggplot(df_nw, aes(x=date, y=net_worth, colour=commodity, group=commodity)) +
  geom_line() + scale_y_continuous(labels=scales::dollar)
Basic net worth chart

Basic net worth chart

month_cutoff <- zoo::as.yearmon(Sys.Date()) - 2/12
compute_income <- function(df) {
    count_beans(df, "^Income", yearmon) %>%
        mutate(income = -amount) %>%
        select(-amount) %>% ungroup()
}
print_income <- function(df) {
    compute_income(df) %>%
        filter(yearmon >= month_cutoff) %>%
        spread(yearmon, income, fill=0) %>%
        print_tibble_rows()
}
compute_expenses <- function(df) {
    count_beans(df, "^Expenses", yearmon) %>%
        mutate(expenses = amount) %>%
        select(-amount) %>% ungroup()
}
print_expenses <- function(df) {
    compute_expenses(df) %>%
        filter(yearmon >= month_cutoff) %>%
        spread(yearmon, expenses, fill=0) %>%
        print_tibble_rows()
}
compute_total <- function(df) {
full_join(compute_income(prune_coa(df)) %>% select(-account),
          compute_expenses(prune_coa(df)) %>% select(-account),
          by=c("yearmon", "commodity")) %>%
    mutate(income = ifelse(is.na(income), 0, income),
           expenses = ifelse(is.na(expenses), 0, expenses),
           net = income - expenses) %>%
    gather(type, amount, -yearmon, -commodity)
}
print_total <- function(df) {
    compute_total(df) %>%
        filter(yearmon >= month_cutoff) %>%
        spread(yearmon, amount, fill=0) %>%
        print_tibble_rows()
}
print_total(df)
## # A tibble: 3 × 5
##   commodity type     `Mar 2024` `Apr 2024` `May 2024`
##   <chr>     <chr>         <dbl>      <dbl>      <dbl>
## 1 USD       expenses      8706.      7496.      2248.
## 2 USD       income       11115.     10479.      5240.
## 3 USD       net           2410.      2984.      2992.
print_income(prune_coa(df, 2))
## # A tibble: 1 × 5
##   account   commodity `Mar 2024` `Apr 2024` `May 2024`
##   <chr>     <chr>          <dbl>      <dbl>      <dbl>
## 1 Income:US USD           11115.     10479.      5240.
print_expenses(prune_coa(df, 2))
## # A tibble: 6 × 5
##   account            commodity `Mar 2024` `Apr 2024` `May 2024`
##   <chr>              <chr>          <dbl>      <dbl>      <dbl>
## 1 Expenses:Financial USD             39.8         4        13.0
## 2 Expenses:Food      USD            649.        592.      146.
## 3 Expenses:Health    USD            194.        194.       96.9
## 4 Expenses:Home      USD           2612.       2602.        0
## 5 Expenses:Taxes     USD           5092.       3984.     1992.
## 6 Expenses:Transport USD            120         120         0
print_income(df)
## # A tibble: 5 × 5
##   account                         commodity `Mar 2024` `Apr 2024` `May 2024`
##   <chr>                           <chr>          <dbl>      <dbl>      <dbl>
## 1 Income:US:BayBook:GroupTermLife USD             48.6       48.6       24.3
## 2 Income:US:BayBook:Match401k     USD           1800       1200        600
## 3 Income:US:BayBook:Salary        USD           9231.      9231.      4615.
## 4 Income:US:ETrade:GLD:Dividend   USD             95.9        0          0
## 5 Income:US:ETrade:PnL            USD            -59.8        0          0
print_expenses(df)
## # A tibble: 21 × 5
##    account                            commodity `Mar 2024` `Apr 2024` `May 2024`
##    <chr>                              <chr>          <dbl>      <dbl>      <dbl>
##  1 Expenses:Financial:Commissions     USD            35.8        0          8.95
##  2 Expenses:Financial:Fees            USD             4          4          4
##  3 Expenses:Food:Groceries            USD           282.       270.        66.2
##  4 Expenses:Food:Restaurant           USD           367.       321.        79.4
##  5 Expenses:Health:Dental:Insurance   USD             5.8        5.8        2.9
##  6 Expenses:Health:Life:GroupTermLife USD            48.6       48.6       24.3
##  7 Expenses:Health:Medical:Insurance  USD            54.8       54.8       27.4
##  8 Expenses:Health:Vision:Insurance   USD            84.6       84.6       42.3
##  9 Expenses:Home:Electricity          USD            65         65          0
## 10 Expenses:Home:Internet             USD            80.1       80.0        0
## 11 Expenses:Home:Phone                USD            66.4       57.1        0
## 12 Expenses:Home:Rent                 USD          2400       2400          0
## 13 Expenses:Taxes:Y2023:US:Federal    USD           632.         0          0
## 14 Expenses:Taxes:Y2023:US:State      USD           476.         0          0
## 15 Expenses:Taxes:Y2024:US:CityNYC    USD           350.       350.       175.
## 16 Expenses:Taxes:Y2024:US:Federal    USD          2126.      2126.      1063.
## 17 Expenses:Taxes:Y2024:US:Medicare   USD           213.       213.       107.
## 18 Expenses:Taxes:Y2024:US:SDI        USD             2.24       2.24       1.12
## 19 Expenses:Taxes:Y2024:US:SocSec     USD           563.       563.       282.
## 20 Expenses:Taxes:Y2024:US:State      USD           730.       730.       365.
## 21 Expenses:Transport:Tram            USD           120        120          0

And here is a plot of income, expenses, and net income over time:

ggplot(compute_total(df), aes(x=yearmon, y=amount, group=commodity, colour=commodity)) +
  facet_grid(type ~ .) +
  geom_line() + geom_hline(yintercept=0, linetype="dashed") +
  scale_x_continuous() + scale_y_continuous(labels=scales::comma)
Monthly income chart

Monthly income chart

r-ledger's People

Contributors

esovetkin avatar trevorld avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

r-ledger's Issues

"register_hledge()" fails with comma as currency separator and/or if the commodity is prefixed

Hi

As the title states, register_hledge fails if the currency is formatted with a comma as the decimal separator and/or the commodity is prefixed. It will import the transactions, but all amounts will be NA. All of these formats are the official format somewhere.

I found possible solutions (see below) such that the user doesn't need to change his original hledger files and where the internals of register_hledge stays roughly the same, with a few additions.

I have not yet implemented the solutions, but if you agree with them i can make a pull request.

Either way, it took me some time to find error so i believe a more descriptive error message would be good.

Reproducible code

Note that this will create a file called "temp.journal" in the current directory)

> writeLines(c("2016/01/01 Rent", "    assets    100.00 EUR","    expenses"), "temp.journal")
> register_hledger("temp.journal") # works
# A tibble: 2 x 11
  date       mark  payee description account amount commodity historical_cost
  <date>     <chr> <lgl> <chr>       <chr>    <dbl> <chr>               <dbl>
1 2016-01-01 ""    NA    Rent        assets     100 EUR                   100
2 2016-01-01 ""    NA    Rent        expens…   -100 EUR                  -100
...
> writeLines(c("2016/01/01 Rent", "    assets    100,00 EUR","    expenses"), "temp.journal")
> register_hledger("temp.journal") # will import NAs
# A tibble: 2 x 11
  date       mark  payee description account amount commodity historical_cost
  <date>     <chr> <lgl> <chr>       <chr>    <dbl> <chr>               <dbl>
1 2016-01-01 ""    NA    Rent        assets      NA EUR                    NA
2 2016-01-01 ""    NA    Rent        expens…     NA EUR                    NA
# … with 3 more variables: hc_commodity <chr>, market_value <dbl>,
#   mv_commodity <chr>
Warning messages:
1: NAs introduced by coercion 
2: NAs introduced by coercion 
3: NAs introduced by coercion 
> writeLines(c("2016/01/01 Rent", "    assets    EUR 100.00","    expenses"), "temp.journal")
> register_hledger("temp.journal") # Will import NAs
# A tibble: 2 x 11
  date       mark  payee description account amount commodity historical_cost
  <date>     <chr> <lgl> <chr>       <chr>    <dbl> <chr>               <dbl>
1 2016-01-01 ""    NA    Rent        assets      NA 100.00                 NA
2 2016-01-01 ""    NA    Rent        expens…     NA -100.00                NA
# … with 3 more variables: hc_commodity <chr>, market_value <dbl>,
#   mv_commodity <chr>
Warning messages:
1: NAs introduced by coercion 
2: NAs introduced by coercion 
3: NAs introduced by coercion 
> writeLines(c("2016/01/01 Rent", "    assets    EUR 100,00","    expenses"), "temp.journal")
> register_hledger("temp.journal") "will imports NAs"
# A tibble: 2 x 11
  date       mark  payee description account amount commodity historical_cost
  <date>     <chr> <lgl> <chr>       <chr>    <dbl> <chr>               <dbl>
1 2016-01-01 ""    NA    Rent        assets      NA 100,00                 NA
2 2016-01-01 ""    NA    Rent        expens…     NA -100,00                NA
# … with 3 more variables: hc_commodity <chr>, market_value <dbl>,
#   mv_commodity <chr>
Warning messages:
1: NAs introduced by coercion 
2: NAs introduced by coercion 
3: NAs introduced by coercion 

Solutions

Commodity placement

Using hledge print -o file.csv instead of hledge register -o file.csv yields a file with all the information from using register but where the amount is split into an "amount" and "commodity" field. Hence the commodity could be extracted from that column.

For example: (using the same temp.journal from above)

$ hledger register -f temp.journal -o tempReg.csv
$ hledger print -f temp.journal -o tempPrint.csv
$ cat tempReg.csv
"txnidx","date","code","description","account","amount","total"
"1","2016/01/01","","Rent","assets","EUR 100,00","EUR 100,00"
"1","2016/01/01","","Rent","expenses","EUR -100,00","0"
$ cat tempPrint.csv
"txnidx","date","date2","status","code","description","comment","account","amount","commodity","credit","debit","posting-status","posting-comment"
"1","2016/01/01","","","","Rent","","assets","100,00","EUR","","100,00","",""
"1","2016/01/01","","","","Rent","","expenses","-100,00","EUR","100,00","","",""

The columns are named in the same way, so it wouldn't change much.

Decimal separator

This solution is a bit more "hacky" but I believe it's pretty robust.

hledger allows one to specify commodity directives with commodity 100.00 USD - but it has to be a part of the journal file. So a possible solution could work like

  • Use hledger print -o file.csv to find all commodities in use, like above
  • create a copy of the journal file
  • for each commodity, insert the line "commodity 100.00 <commodity>" at the end of the file
  • use hledger register exactly as in the original implementation.
    I have tried it with a single commodity and it worked.

Add engine argument

Refine unit tests for beancount to check for both bean-report and other engines

Import `beancount` metadata

Is there support for reading metadata? I can't see the metadata in the beancount file I am reading with ledger. Unless I am missing something.

Read beancount files in directly with an appropriate bean-query statement

Currently use either bean-report (h)ledger and then either ledger csv or hledger register -o csv. Right now bean-query "SELECT *" doesn't give me what I want/need (in particular missing the crucial account field plus parsing historical cost and/or market values look like could be a bit of a pain as well):

$ bean-example > example.bean
$ bean-query -f csv example.bean "SELECT *" | csvlook | head
|-------------+------+---------------------------+--------------------------------------------------+---------------------------------|
|  date       | flag | payee                     | narration                                        | position                        |
|-------------+------+---------------------------+--------------------------------------------------+---------------------------------|
|  2016-01-01 | *    |                           | Opening Balance for checking account             |   3762.36  USD                  |
|  2016-01-01 | *    |                           | Opening Balance for checking account             |  -3762.36  USD                  |
|  2016-01-01 | *    |                           | Allowed contributions for one year               | -18000     IRAUSD               |
|  2016-01-01 | *    |                           | Allowed contributions for one year               |  18000     IRAUSD               |
|  2016-01-03 | *    | RiverBank Properties      | Paying the rent                                  |  -2400.00  USD                  |
|  2016-01-03 | *    | RiverBank Properties      | Paying the rent                                  |   2400.00  USD                  |
|  2016-01-04 | *    | BANK FEES                 | Monthly bank fee                                 |     -4.00  USD                  |

Enhance register output and simplify register arguments

Add mark, cost, cost_commodity, value, value_commodity columns to imported data frame. Do this by importing in the register several times with a helper function and then merge/join them. Also add an end date option to the helper function to aid with net worth at various times calculations.

For `beancount` add `id` column

beancount has an id that uniquely identifies each entry. I think it would be helpful if the id is also imported into the data frame.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.