Skip to content

Commit 675f317

Browse files
author
hagan
committed
all period to date functions work and pass tests
1 parent 6f63682 commit 675f317

File tree

6 files changed

+211
-8
lines changed

6 files changed

+211
-8
lines changed

R/abc.R

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ abc_fn <- function(x){
158158
dplyr::select(
159159
-dist_rank,
160160
-category_value,
161-
-row_id,
162161
-max_row_id,
163162
-cum_unit_prop
164163
)

R/utils-sql.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ seq_date_sql <- function(start_date, end_date, time_unit, .con) {
4949

5050
# 2. Variable Prep -------------------------------------------------------
5151
unit <- tolower(time_unit)
52-
is_duckdb_pg <- inherits(.con, "duckdb_.connection") || inherits(.con, "Pq.connection")
52+
is_duckdb_pg <- inherits(.con, "duckdb_connection") || inherits(.con, "Pqconnection")
5353
is_snowflake <- inherits(.con, "Snowflake")
5454
is_test <- inherits(.con, "Test.connection")
5555

tests/testthat.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file is part of the standard setup for testthat.
2+
# It is recommended that you do not modify it.
3+
#
4+
# Where should you do additional test configuration?
5+
# Learn more about the roles of various files in:
6+
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
7+
# * https://testthat.r-lib.org/articles/special-files.html
8+
9+
library(testthat)
10+
library(fpaR)
11+
12+
test_check("fpaR")

tests/testthat/test-ti.R

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
library(testthat)
2+
library(dplyr)
3+
library(lubridate)
4+
5+
# We skip these tests if 'contoso' isn't available, preventing errors on systems without the data
6+
skip_if_not_installed("contoso")
7+
8+
describe("Year-related functions (YTD)", {
9+
10+
it("calculates YTD margin with standard calendar (grouped)", {
11+
result <- contoso::sales |>
12+
group_by(store_key) |>
13+
ytd(order_date, margin, "standard") |>
14+
calculate() |>
15+
collect()
16+
17+
expect_s3_class(result, "data.frame")
18+
expect_true("ytd_margin" %in% names(result))
19+
expect_gt(nrow(result), 0)
20+
})
21+
22+
it("calculates YTD margin with 445 calendar (grouped by customer)", {
23+
result <- contoso::sales |>
24+
group_by(customer_key) |>
25+
ytd(order_date, margin, "445") |>
26+
calculate() |>
27+
collect() # Added collect() to ensure we get data back
28+
29+
expect_true("ytd_margin" %in% names(result))
30+
expect_gt(nrow(result), 0)
31+
})
32+
})
33+
34+
describe("Quarter, Month, Week to Date (QTD, MTD, WTD)", {
35+
36+
it("calculates QTD, MTD, WTD correctly", {
37+
# QTD Standard
38+
res_qtd <- contoso::sales |>
39+
qtd(order_date, margin, "standard") |>
40+
calculate() |>
41+
collect()
42+
expect_true("qtd_margin" %in% names(res_qtd))
43+
44+
# MTD 445
45+
res_mtd <- contoso::sales |>
46+
mtd(order_date, margin, "445") |>
47+
calculate() |>
48+
collect()
49+
expect_true("mtd_margin" %in% names(res_mtd))
50+
51+
# WTD Standard
52+
res_wtd <- contoso::sales |>
53+
wtd(order_date, margin, "standard") |>
54+
calculate() |>
55+
collect()
56+
expect_true("wtd_margin" %in% names(res_wtd))
57+
})
58+
59+
it("calculates ATD (All-to-date)", {
60+
result <- contoso::sales |>
61+
group_by(store_key) |>
62+
atd(order_date, margin, "445") |>
63+
calculate() |>
64+
collect()
65+
66+
expect_true("atd_margin" %in% names(result))
67+
})
68+
})
69+
70+
describe("Period Over Period (YOY, QOQ, MOM, WOW, DOD)", {
71+
72+
it("calculates YOY margin and filters specific store", {
73+
result <- contoso::sales |>
74+
group_by(store_key) |>
75+
yoy(order_date, margin, "standard", 1) |>
76+
calculate() |>
77+
collect() |> # Collect before filtering in R if strictly checking logic, or keep lazy if supported
78+
filter(store_key == "999999")
79+
80+
expect_true("yoy_margin" %in% names(result))
81+
})
82+
83+
it("calculates QOQ, MOM, WOW, DOD", {
84+
# QOQ
85+
res_qoq <- contoso::sales |> qoq(order_date, margin, "standard") |> calculate() |> collect()
86+
expect_true("qoq_margin" %in% names(res_qoq))
87+
88+
# MOM
89+
res_mom <- contoso::sales |> mom(order_date, margin, "445") |> calculate() |> collect()
90+
expect_true("mom_margin" %in% names(res_mom))
91+
92+
# WOW
93+
res_wow <- contoso::sales |> wow(order_date, margin, "standard") |> calculate() |> collect()
94+
expect_true("wow_margin" %in% names(res_wow))
95+
96+
# DOD
97+
res_dod <- contoso::sales |> dod(order_date, margin, "standard") |> calculate() |> collect()
98+
expect_true("dod_margin" %in% names(res_dod))
99+
})
100+
})
101+
102+
describe("Prior Period to Current YTD/QTD/MTD", {
103+
104+
it("calculates YOYTD (Year Over Year To Date)", {
105+
result <- contoso::sales |>
106+
fpaR::yoytd(order_date, margin, "standard", 1) |>
107+
calculate() |>
108+
collect()
109+
110+
expect_true("pytd_margin" %in% names(result)) # Based on your filter snippet
111+
expect_true("ytd_margin" %in% names(result))
112+
})
113+
114+
it("calculates QOQTD and MOMTD", {
115+
# QOQTD
116+
res_qoqtd <- contoso::sales |> fpaR::qoqtd(order_date, margin, "standard", 1) |> calculate() |> collect()
117+
expect_true("pqtd_margin" %in% names(res_qoqtd))
118+
119+
# MOMTD
120+
res_momtd <- contoso::sales |> fpaR::momtd(order_date, margin, "standard", 1) |> calculate() |> collect()
121+
expect_true("pmtd_margin" %in% names(res_momtd))
122+
})
123+
124+
it("calculates WOWTD", {
125+
result <- contoso::sales |>
126+
fpaR::wowtd(order_date, margin, calendar_type = "standard", lag_n = 1) |>
127+
calculate() |>
128+
collect()
129+
130+
expect_s3_class(result, "data.frame")
131+
})
132+
})
133+
134+
describe("Prior To Date Functions (PYTD, PQTD, PMTD, PWTD)", {
135+
136+
it("calculates pure Prior YTD/QTD/MTD/WTD columns", {
137+
# PYTD
138+
res_pytd <- contoso::sales |> fpaR::pytd(order_date, margin, "standard", 1) |> calculate() |> collect()
139+
expect_true("pytd_margin" %in% names(res_pytd))
140+
141+
# PQTD
142+
res_pqtd <- contoso::sales |> fpaR::pqtd(order_date, margin, "standard", 1) |> calculate() |> collect()
143+
expect_true("pqtd_margin" %in% names(res_pqtd))
144+
145+
# PWTD
146+
res_pwtd <- contoso::sales |> fpaR::pwtd(order_date, margin, "standard", 1) |> calculate() |> collect()
147+
expect_true("pwtd_margin" %in% names(res_pwtd))
148+
})
149+
})
150+
151+
describe("Complex Comparisons (YTDOPY, MTDOPM, etc)", {
152+
153+
it("calculates YTD over Prior Year", {
154+
result <- contoso::sales |>
155+
fpaR::ytdopy(order_date, margin, calendar_type="standard", lag_n = 1) |>
156+
calculate() |>
157+
collect()
158+
159+
expect_true("yoy_margin" %in% names(result))
160+
})
161+
162+
it("calculates MTD over Prior Month", {
163+
result <- contoso::sales |>
164+
fpaR::mtdopm(order_date, margin, calendar_type="standard", lag_n = 1) |>
165+
calculate() |>
166+
collect()
167+
168+
expect_true("mom_margin" %in% names(result))
169+
})
170+
})
171+
172+
describe("Special Functions (ABC, Cohort)", {
173+
174+
it("performs ABC analysis", {
175+
result <- contoso::sales |>
176+
group_by(store_key) |>
177+
fpaR::abc(category_values = c(.3,.5,.7,.8), .value = margin) |>
178+
calculate() |>
179+
collect()
180+
181+
# Typically ABC adds a category/class column, check for that or the value
182+
expect_gt(nrow(result), 0)
183+
})
184+
185+
it("performs Cohort analysis", {
186+
result <- contoso::sales |>
187+
group_by(store_key) |>
188+
fpaR::cohort(.date = order_date, .value = margin, time_unit = "month", period_label = FALSE) |>
189+
calculate() |>
190+
collect()
191+
192+
expect_gt(nrow(result), 0)
193+
})
194+
})

vignettes/articles/abc.qmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The `abc()` function applies this method by ranking group members according to e
2828
2929
**Value Capture**
3030

31-
- If `.value` is provided, then that column is aggregate per group member; otherwise, it counts rows
31+
- If `.value` is provided, then that column is aggregated per group member; otherwise, it counts rows
3232

3333
**Category Values**
3434

@@ -160,7 +160,7 @@ tibble::tibble(
160160
"The cumulative proportion of the total, showing the running total percentage of the entire dataset as you move through the rows.",
161161
"The unique identifier for the row, often used to track or identify specific rows in the dataset. Typically sequential ID or index.",
162162
"The maximum row ID in the current group (if grouping is applied), representing the total number of rows in the group.",
163-
"The cumulative proportion of the unit values, similar to cum_prop_total, but typically used when the unit is treated as aggregate.",
163+
"The cumulative proportion of the unit values, similar to cum_prop_total, but typically used when the unit is aggregated.",
164164
"The category value that corresponds to the cumulative proportion break points (e.g., top 10%, top 40%, etc.). Based on the break points provided.",
165165
"The name of the category assigned to each row based on the cumulative contribution. Categories are represented by letters (A, B, C, etc.)."
166166
),

vignettes/articles/cohort.qmd

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The `cohort()` function in **fpaR** provides a **tibble and database-friendly im
2525

2626
- Assigns each member in your dataset to a **time-based cohort** based on the first occurrence in the `.date` column
2727
- Aggregates distinct counts of cohort members over time
28-
- Supports multiple calendar types (`"standard"` or a non-standard calendar `"544"`) and `time_unit` (`day`, `week`, `month`, `quarter`, `year`)
28+
- Supports multiple time units (`day`, `week`, `month`, `quarter`, `year`)
2929
- Returns a **segment object**, which can be processed using `calculate()` to generate the cohort table
3030

3131
# Arguments
@@ -35,8 +35,7 @@ The `cohort()` function in **fpaR** provides a **tibble and database-friendly im
3535
| `.data` | A `tibble` or DBI object containing your dataset. |
3636
| `.date` | The date column to base the cohort assignment on. |
3737
| `.value` | The column representing members to track (e.g., customer ID). |
38-
| `calendar_type` | Type of calendar to use for aggregation: `"standard"` or `"554"`. |
39-
| `time_unit` | Time unit to summarize the cohort table by (`day`, `week`, `month`, `quarter`, `year`). Default is `"month"`. |
38+
| `time_unit` | Argument to group your calendar dates: `day`, `week`,`month`,`quarter` or `year` |
4039
| `period_label` | Whether to use numeric period labels (`TRUE`) or actual dates (`FALSE`). Default is `FALSE`. |
4140

4241

@@ -52,7 +51,6 @@ The function returns a **segment_cohort** object. Use `calculate()` to retrieve
5251
fpaR::cohort(.data = contoso::sales,
5352
.date = order_date,
5453
.value = customer_key,
55-
calendar_type = "standard",
5654
time_unit = "month",
5755
period_label = FALSE
5856
)

0 commit comments

Comments
 (0)