# Define the example TERR function:
#----
countDaysBetweenGaps <-
function(
InDF = DataDF,
GroupColumn = "Group",
DateColumn = "Date",
ProdColumn = "Prod",
ReturnAllInputColumns = FALSE,
ShowDetails = FALSE )
{
#####
# A gap is defined as a sequence of one or more days (DateColumn)
# within a group (GroupColumn) for which total production (ProdColumn)
# is zero (i.e., production is zero for all units in the group).
#
# The output column ("DaysCount") tallies the cumulative number of days
# since the end of the previous gap in production, for each group
# of production units.
#
# Gaps are assigned a value of NA (missing value) in this output column.
#
# The output column's cumulative count of production days is restarted
# at 1 after the end of each production gap.
#
# Assumptions:
# - DateColumn is a TERR column of class "POSIXct"
# - Within each group, there are no missing dates in the DateColumn
# - ProdColumn is sum of the production on that day for all units in the group
#####
if( ! ReturnAllInputColumns )
{
InDF <- InDF[, c( GroupColumn, DateColumn, ProdColumn ) ]
}
InDF <- InDF[ order(InDF[, GroupColumn], InDF[, DateColumn]), ]
ProdSign <- abs( sign(InDF[, ProdColumn] ) )
ProdSignMask <- ifelse( ProdSign, 1, NA )
Regime <- paste( InDF[, GroupColumn], ProdSign, sep = "." )
RegimeRunLengths <- rle(Regime)$length
RegimeID <-
rep(
x = seq( along = RegimeRunLengths ),
times = RegimeRunLengths )
RawCount <-
unname(
unlist(
lapply(
X = split( InDF[, DateColumn], RegimeID ),
FUN = function(X)
{
c(1, 1 + cumsum( as.integer( diff( X ) / 86400 ) ) )
} ) ) )
DaysCount <- RawCount * ProdSignMask
if( ShowDetails )
{
return(
data.frame(
InDF,
ProdSign,
ProdSignMask,
RegimeID,
RawCount,
DaysCount ) )
}
data.frame( InDF, DaysCount )
}
#----
###################################
# Import the test data set from the
# attached "DataDF.sbdf" file:
PathToTestDataFile <- "c:/data"
file.exists(
file.path( PathToTestDataFile, "DataDF.sbdf" ) )
DataDF <-
SpotfireData::importDataFromSBDF(
file.path( PathToTestDataFile, "DataDF.sbdf" ) )
# Test the example function:
OutDF <- countDaysBetweenGaps(
InDF = DataDF,
GroupColumn = "Group",
DateColumn = "Date",
ProdColumn = "Prod",
ReturnAllInputColumns = TRUE,
ShowDetails = TRUE )
OutDF
###################################
The following shows the contents of the "OutDF" object, along with the four columns of input data (three of which are used in the function) and intermediate steps used in calculation of its "DaysCount" output column.
>
>
> OutDF
Group Unit Date Prod ProdSign ProdSignMask RegimeID RawCount DaysCount
1 A1 zq56 2016-11-10 7 1 1 1 1 1
2 A1 zq53 2016-11-10 7 1 1 1 1 1
3 A1 zq72 2016-11-10 7 1 1 1 1 1
4 A1 zq59 2016-11-11 8 1 1 1 2 2
5 A1 zq75 2016-11-11 8 1 1 1 2 2
6 A1 zq78 2016-11-11 8 1 1 1 2 2
7 A1 zq67 2016-11-11 8 1 1 1 2 2
8 A1 zq56 2016-11-12 0 0 NA 2 1 NA
9 A1 zq53 2016-11-12 0 0 NA 2 1 NA
10 A1 zq72 2016-11-12 0 0 NA 2 1 NA
11 A1 zq59 2016-11-12 0 0 NA 2 1 NA
12 A1 zq75 2016-11-12 0 0 NA 2 1 NA
13 A1 zq78 2016-11-12 0 0 NA 2 1 NA
14 A1 zq67 2016-11-12 0 0 NA 2 1 NA
15 A1 zq53 2016-11-13 3 1 1 3 1 1
16 A1 zq72 2016-11-13 3 1 1 3 1 1
17 A1 zq59 2016-11-13 3 1 1 3 1 1
18 A1 zq75 2016-11-13 3 1 1 3 1 1
19 A1 zq78 2016-11-13 3 1 1 3 1 1
20 B2 zq27 2016-11-10 9 1 1 4 1 1
21 B2 zq32 2016-11-10 9 1 1 4 1 1
22 B2 zq38 2016-11-10 9 1 1 4 1 1
23 B2 zq19 2016-11-11 0 0 NA 5 1 NA
24 B2 zq24 2016-11-11 0 0 NA 5 1 NA
25 B2 zq10 2016-11-11 0 0 NA 5 1 NA
26 B2 zq16 2016-11-11 0 0 NA 5 1 NA
27 B2 zq27 2016-11-12 5 1 1 6 1 1
28 B2 zq32 2016-11-12 5 1 1 6 1 1
29 B2 zq38 2016-11-12 5 1 1 6 1 1
30 B2 zq19 2016-11-13 3 1 1 6 2 2
31 B2 zq24 2016-11-13 3 1 1 6 2 2
32 B2 zq10 2016-11-13 3 1 1 6 2 2
33 B2 zq16 2016-11-13 3 1 1 6 2 2
34 B2 zq10 2016-11-14 4 1 1 6 3 3
35 B2 zq16 2016-11-14 4 1 1 6 3 3
36 B2 zq27 2016-11-15 2 1 1 6 4 4
37 B2 zq32 2016-11-15 2 1 1 6 4 4
38 B2 zq38 2016-11-15 2 1 1 6 4 4
>
>
More information on TERR functions used in this example can be found in the Help files that are opened by the following TERR commands.
?POSIXct
?order
?abs
?sign
?paste
?rle
?seq
?rep
?ifelse
?unname
?unlist
?lapply
?split
?c
?cumsum
?as.integer
?diff
?data.frame
?return
?file.path
?file.exists
help( "importDataFromSBDF", try.all.packages = TRUE )
Disclaimer:
The code in this article is only a sample to be used as a reference. It is not intended to be used "As Is" in a Production environment. Always test in a Development environment. Make modifications to the code in accordance with your implementation specifications that best suit your business requirements. Refer to the reference(s) cited in this article for usage of the functions and methods used in the code.