From 48d133a2aae8579d82d6dd4f4c2b2a8e52f10f93 Mon Sep 17 00:00:00 2001
From: Bergant <darko.bergant@adacta.si>
Date: Sat, 28 Mar 2015 14:19:41 +0100
Subject: [PATCH] calculate

calculate
---
 DESCRIPTION                  |   3 +-
 NAMESPACE                    |   4 +-
 R/finstr.R                   | 131 ++++++++---------------------------
 man/calculate.Rd             |  32 +++++++++
 man/expose.Rd                |  54 ---------------
 man/finstr-package.Rd        |  14 ++--
 man/get_elements.Rd          |   2 +-
 man/grapes-without-grapes.Rd |  18 -----
 man/other.Rd                 |  16 -----
 man/xbrl_create_data.Rd      |   1 +
 vignettes/Overview.Rmd       |  43 +++++++++---
 11 files changed, 104 insertions(+), 214 deletions(-)
 create mode 100644 man/calculate.Rd
 delete mode 100644 man/expose.Rd
 delete mode 100644 man/grapes-without-grapes.Rd
 delete mode 100644 man/other.Rd

diff --git a/DESCRIPTION b/DESCRIPTION
index 9100be3..3190962 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -14,7 +14,8 @@ Imports:
     dplyr,
     tidyr,
     XBRL,
-    RCurl
+    RCurl,
+    lazyeval
 Suggests: testthat,
     knitr
 VignetteBuilder: knitr
diff --git a/NAMESPACE b/NAMESPACE
index 97e0306..87b0340 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -6,11 +6,9 @@ S3method(print,elements)
 S3method(print,statement)
 S3method(print,statements)
 S3method(print,xbrl_vars)
-export("%without%")
-export(expose)
+export(calculate)
 export(get_elements)
 export(get_elements_hierarchy)
-export(other)
 export(xbrl_get_relations)
 export(xbrl_get_statement_ids)
 export(xbrl_get_statements)
diff --git a/R/finstr.R b/R/finstr.R
index 47c385e..ee61e9f 100644
--- a/R/finstr.R
+++ b/R/finstr.R
@@ -22,6 +22,7 @@ NULL
 #' Function to create package data included in the package
 #' 
 #' @details xbrlDoAll creates > 5Mb list - we need only 2Mb
+#' @keywords internal
 xbrl_create_data <-function() {
 
   file1 <- "http://edgar.sec.gov/Archives/edgar/data/320193/000119312513416534/aapl-20130928.xml"
@@ -358,7 +359,7 @@ xbrl_get_statements <- function(xbrl_vars, rm_prefix = "us-gaap_") {
 #' @param x A statement object
 #' @param parent_id used as filter if defined
 #' @param all if FALSE only terminal elements from the hierarchy will be returned
-#' @seealso \code{\link{get_elements}} and \code{\link{expose}}
+#' @seealso \code{\link{calculate}}
 #' @export
 get_elements <- function(x, parent_id = NULL, all = TRUE) {
   # returns all terminating elements 
@@ -396,108 +397,6 @@ as.elements <- function(x) {
   return(x)
 }
 
-#' Calculate higher order element values
-#' 
-#' @param x a statement object
-#' @param ... elements of the statement
-#' @return a statement object
-#' @description Generate statement with agregated values. 
-#' @details expose uses calculation link base hierarchy to find 
-#' which concept to include in the aggregate. The aggregation function is
-#' always \emph{sum}. See examples for more details.
-#' @examples
-#' \dontrun{
-#' 
-#' # total assets
-#' st1$StatementOfFinancialPositionClassified %>%
-#'   expose(
-#'     "Assets" 
-#'   )
-#'
-#' # current and non-current assets (using other)  
-#' st1$StatementOfFinancialPositionClassified %>%
-#'   expose(
-#'     CurrentAssets = "AssetsCurrent", 
-#'     NoncurrentAssets = other("Assets"),
-#'     "LiabilitiesAndStockholdersEquity"
-#'   )
-#'   
-#' # calculate non-current assets (using %without% operator)   
-#' st1$StatementOfFinancialPositionClassified %>%
-#'   expose(
-#'     NoncurrentAssets = "Assets" %without% "AssetsCurrent",
-#'     CurrentAssets = "AssetsCurrent", 
-#'     "LiabilitiesAndStockholdersEquity"
-#'   )
-#' }
-#' 
-#' @seealso \link{finstr}
-#' @export
-expose <- function(x, ...) {
-  stop("Under construction")
-  elements <- list(...)
-  # prepare for "other" and "without" directive
-  used_cols <- c()
-  for(i in seq_along(elements)) {
-    cols <- get_elements(x, elements[[i]])
-    if(elements[[i]][1] == "")
-      cols <- get_elements(x)
-    el_type <- attr(elements[[i]], "type")
-    if( !is.null(el_type) && el_type == "other") {
-      cols <- cols[ !cols %in% used_cols]
-      elements[[i]] <- cols
-    } 
-    if( !is.null(el_type) && el_type == "without") {
-      e1 <- get_elements(x, elements[[i]][[1]])
-      e2 <- get_elements(x, elements[[i]][[2]])
-      cols <- e1[!e1 %in% e2]
-      elements[[i]] <- cols
-    }
-    used_cols <- union(used_cols, cols)
-  }
-  
-  res <- 
-    data.frame(
-      do.call(
-        cbind,
-        lapply(elements, function(element) {
-          cols <- get_elements(x, element)
-          cbind(rowSums(x[cols]))
-        })
-      )
-    )
-  names(res) <- elements
-  names(res)[names(elements)!=""] <- names(elements)[names(elements)!=""]
-  res <- cbind(x[,1:4], res )
-  class(res) <- c("statement", "data.frame")
-  return(res)
-}
-
-#' Used in expose to sum the concepts not already used 
-#' 
-#' @param element element from concept hierarchy 
-#' @keywords internal
-#' @export
-other <- function(element = NULL) {
-  if(missing(element)){
-    element <- ""
-  }
-  attr(element, "type") <- "other"
-  return(element)
-}
-
-#' Used in expose to sum the concepts under e1 without e2 
-#' 
-#' @param e1 element group
-#' @param e2 element group not to be included
-#' @keywords internal
-#' @export
-'%without%' <- function(e1, e2) {
-  x <- list(e1, e2)
-  attr(x, "type") <- "without"
-  return(x)
-}
-
 #' Merge two financial statements
 #' 
 #' @description Merge two statements from different time periods.
@@ -577,4 +476,30 @@ merge.statements <- function(x, y, ...) {
   return(z)
 }
 
+#' Calculate formulas 
+#' 
+#' @param x a statement object
+#' @param ... list of formulas
+#' @examples
+#' \dontrun{
+#' 
+#' balance_sheet %>% calculate(
+#'   
+#'   current_ratio = AssetsCurrent / LiabilitiesCurrent,
+#'   
+#'   quick_ratio =  
+#'     ( CashAndCashEquivalentsAtCarryingValue + 
+#'         AvailableForSaleSecuritiesCurrent +
+#'         AccountsReceivableNetCurrent
+#'       ) / LiabilitiesCurrent
+#' )
+#' }
+#' @export
+calculate <- function(x, ...) {
+
+  #dplyr::transmute_(x, endDate = ~endDate, .dots = lazyeval::lazy_dots(...))
+  dplyr::transmute_(x, endDate = ~endDate, .dots = lazyeval::lazy_dots(...)) %>%
+    dplyr::select(everything(), -matches("^\\."))
+  
+}
 
diff --git a/man/calculate.Rd b/man/calculate.Rd
new file mode 100644
index 0000000..0273b19
--- /dev/null
+++ b/man/calculate.Rd
@@ -0,0 +1,32 @@
+% Generated by roxygen2 (4.1.0): do not edit by hand
+% Please edit documentation in R/finstr.R
+\name{calculate}
+\alias{calculate}
+\title{Calculate formulas}
+\usage{
+calculate(x, ...)
+}
+\arguments{
+\item{x}{a statement object}
+
+\item{...}{list of formulas}
+}
+\description{
+Calculate formulas
+}
+\examples{
+\dontrun{
+
+balance_sheet \%>\% calculate(
+
+  current_ratio = AssetsCurrent / LiabilitiesCurrent,
+
+  quick_ratio =
+    ( CashAndCashEquivalentsAtCarryingValue +
+        AvailableForSaleSecuritiesCurrent +
+        AccountsReceivableNetCurrent
+      ) / LiabilitiesCurrent
+)
+}
+}
+
diff --git a/man/expose.Rd b/man/expose.Rd
deleted file mode 100644
index 8e85c54..0000000
--- a/man/expose.Rd
+++ /dev/null
@@ -1,54 +0,0 @@
-% Generated by roxygen2 (4.1.0): do not edit by hand
-% Please edit documentation in R/finstr.R
-\name{expose}
-\alias{expose}
-\title{Calculate higher order element values}
-\usage{
-expose(x, ...)
-}
-\arguments{
-\item{x}{a statement object}
-
-\item{...}{elements of the statement}
-}
-\value{
-a statement object
-}
-\description{
-Generate statement with agregated values.
-}
-\details{
-expose uses calculation link base hierarchy to find
-which concept to include in the aggregate. The aggregation function is
-always \emph{sum}. See examples for more details.
-}
-\examples{
-\dontrun{
-
-# total assets
-st1$StatementOfFinancialPositionClassified \%>\%
-  expose(
-    "Assets"
-  )
-
-# current and non-current assets (using other)
-st1$StatementOfFinancialPositionClassified \%>\%
-  expose(
-    CurrentAssets = "AssetsCurrent",
-    NoncurrentAssets = other("Assets"),
-    "LiabilitiesAndStockholdersEquity"
-  )
-
-# calculate non-current assets (using \%without\% operator)
-st1$StatementOfFinancialPositionClassified \%>\%
-  expose(
-    NoncurrentAssets = "Assets" \%without\% "AssetsCurrent",
-    CurrentAssets = "AssetsCurrent",
-    "LiabilitiesAndStockholdersEquity"
-  )
-}
-}
-\seealso{
-\link{finstr}
-}
-
diff --git a/man/finstr-package.Rd b/man/finstr-package.Rd
index d9e5a99..f0bb977 100644
--- a/man/finstr-package.Rd
+++ b/man/finstr-package.Rd
@@ -22,9 +22,8 @@ manipulate financial statements data in R.
 \itemize{
 \item
   Convert XBRL (XML files and schemas) to a list of data frames 
-  (facts, contexts, roles and hierarchies) with \code{\link{xbrl_parse_min}} 
-  function. It is using XBRL parsing primitives from \link[XBRL]{XBRL-package} 
-  to parse only minimum data needed to construct financial statements.
+  (facts, contexts, roles and hierarchies) with \link[XBRL]{xbrlDoAll} 
+  function from \link[XBRL]{XBRL-package}. 
 \item
   Function \code{\link{xbrl_get_statements}} converts the XBRL data list
   to \emph{statements} object. It is a list of 
@@ -43,10 +42,11 @@ manipulate financial statements data in R.
 }
 \section{Using Financial Statements Data}{
 \itemize{
-\item To calculate values of higher order concepts and concept 
-  combinations (e.g. \emph{non-current assets}) use \code{\link{expose}} function.
-  The result of expose function is a statement object with transformed concepts 
-  (data frame columns).
+\item To calculate values with formulas use  
+  use \code{\link{calculate}} function or use 
+  statement as a data frame with R base functions or packages 
+  like \link[dplyr]{dplyr} for manipulating data 
+  frames.
 \item
   Function \code{\link{merge.statement}} can merge statements from different
   periods to a single statement. The elements and hierarchies are merged to
diff --git a/man/get_elements.Rd b/man/get_elements.Rd
index c5db7e7..2b615bb 100644
--- a/man/get_elements.Rd
+++ b/man/get_elements.Rd
@@ -17,6 +17,6 @@ get_elements(x, parent_id = NULL, all = TRUE)
 Get the terminating nodes of the calculation hierarchy
 }
 \seealso{
-\code{\link{get_elements}} and \code{\link{expose}}
+\code{\link{calculate}}
 }
 
diff --git a/man/grapes-without-grapes.Rd b/man/grapes-without-grapes.Rd
deleted file mode 100644
index 32ce8af..0000000
--- a/man/grapes-without-grapes.Rd
+++ /dev/null
@@ -1,18 +0,0 @@
-% Generated by roxygen2 (4.1.0): do not edit by hand
-% Please edit documentation in R/finstr.R
-\name{\%without\%}
-\alias{\%without\%}
-\title{Used in expose to sum the concepts under e1 without e2}
-\usage{
-e1 \%without\% e2
-}
-\arguments{
-\item{e1}{element group}
-
-\item{e2}{element group not to be included}
-}
-\description{
-Used in expose to sum the concepts under e1 without e2
-}
-\keyword{internal}
-
diff --git a/man/other.Rd b/man/other.Rd
deleted file mode 100644
index c83e10d..0000000
--- a/man/other.Rd
+++ /dev/null
@@ -1,16 +0,0 @@
-% Generated by roxygen2 (4.1.0): do not edit by hand
-% Please edit documentation in R/finstr.R
-\name{other}
-\alias{other}
-\title{Used in expose to sum the concepts not already used}
-\usage{
-other(element = NULL)
-}
-\arguments{
-\item{element}{element from concept hierarchy}
-}
-\description{
-Used in expose to sum the concepts not already used
-}
-\keyword{internal}
-
diff --git a/man/xbrl_create_data.Rd b/man/xbrl_create_data.Rd
index e1509bd..1ed6b1d 100644
--- a/man/xbrl_create_data.Rd
+++ b/man/xbrl_create_data.Rd
@@ -12,4 +12,5 @@ Function to create package data included in the package
 \details{
 xbrlDoAll creates > 5Mb list - we need only 2Mb
 }
+\keyword{internal}
 
diff --git a/vignettes/Overview.Rmd b/vignettes/Overview.Rmd
index 300155b..bea4d6b 100644
--- a/vignettes/Overview.Rmd
+++ b/vignettes/Overview.Rmd
@@ -108,13 +108,13 @@ balance_sheet <- st_all$StatementOfFinancialPositionClassified
 ## Calculate new values and ratios
 Statement object (in our case `balance_sheet`) is also a data frame object.
 With elements (or concepts) as columns and time periods as rows.
-It is possible then to use statement as a data frame:
+It is possible then to use statement as a data frame.
 
 Lets calculate current ratio which is defined by
 
 $$ Current Ratio = \frac{Current Assets}{Current Liabilities} $$
 
-```{r current_ratio, eval=FALSE}
+```{r dplyr}
 library(dplyr)
 
 balance_sheet %>%
@@ -123,11 +123,31 @@ balance_sheet %>%
 
 ```
 
+By using `calculate` function we can achieve the same result with
+less verbose language. Lets calculate now two ratios:
+
+```{r calculate}
+library(dplyr)
+
+balance_sheet %>% calculate(
+  
+    Current_Ratio = AssetsCurrent / LiabilitiesCurrent,
+    
+    Quick_Ratio =  
+      ( CashAndCashEquivalentsAtCarryingValue + 
+          AvailableForSaleSecuritiesCurrent +
+          AccountsReceivableNetCurrent
+        ) / LiabilitiesCurrent
+    
+)
+```
+
+
 If we need a period average value we can use a `lag` function.
 For example, to calculate *DSO* (days sales outstanding) over longer periods
 the average of account receivable is compared to net sales.
 
-We will use the formula for yearly statements:
+We will use the formula for yearly preiods:
 
 $$ DSO = \frac{Average Accounts Receivable}{Sales Revenue} \times 365 $$
 
@@ -135,16 +155,17 @@ In this case we need to connect two type of statements: balance sheets and
 income statements. With matching reporting periods it can be accomplished 
 with joining two data frames:
 
-```{r DaysSalesOutstanding, eval=FALSE}
+```{r DaysSalesOutstanding}
 
 balance_sheet %>%
   inner_join( st_all$StatementOfIncome, by = "endDate") %>%
-  mutate( 
-    AccountReceivableLast = lag(AccountsReceivableNetCurrent),
-    AccountReceivableAvg = (AccountReceivableLast+AccountsReceivableNetCurrent)/2,
-    DaysSalesOutstanding = AccountReceivableAvg / SalesRevenueNet * 365 
-  ) %>%
-  select(endDate, DaysSalesOutstanding) %>%
-  na.omit()
+  calculate(
+    .AccountReceivableLast = lag(AccountsReceivableNetCurrent),
+    .AccountReceivableAvg = (.AccountReceivableLast + AccountsReceivableNetCurrent)/2,
+    DaysSalesOutstanding = .AccountReceivableAvg / SalesRevenueNet * 365 
+  )
 
 ```
+
+The leading dot instructs the calculate function to hide the value. In our case
+only DaysSalesOutstanding is selected in final result.
-- 
GitLab