Skip to content

Commit

Permalink
Updating to CRAN version 2.2.3
Browse files Browse the repository at this point in the history
Bringing Github back in sync with CRAN versioning - my bad.
  • Loading branch information
killick committed Nov 8, 2022
1 parent e3959de commit 7aacc73
Show file tree
Hide file tree
Showing 20 changed files with 103 additions and 61 deletions.
19 changes: 14 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
Package: changepoint
Type: Package
Title: Methods for Changepoint Detection
Version: 2.2.2
Date: 2016-10-04
Version: 2.2.3
Date: 2022-03-08
Authors@R: c(person("Rebecca", "Killick",
role=c("aut","cre"),email="r.killick@lancs.ac.uk"),
person("Kaylea", "Haynes", role="aut"),
person("Idris", "Eckley", role=c("ths","aut")),
person("Idris", "Eckley", role=c("ths")),
person("Paul","Fearnhead",role=c("ctb","ths")), person("Jamie","Lee",role="ctr"))
Maintainer: Rebecca Killick <r.killick@lancs.ac.uk>
BugReports: <changepoints@lancs.ac.uk>
BugReports: https://github.com/rkillick/changepoint/issues
URL: https://github.com/rkillick/changepoint/
Description: Implements various mainstream and specialised changepoint methods for finding single and multiple changepoints within data. Many popular non-parametric and frequentist methods are included. The cpt.mean(), cpt.var(), cpt.meanvar() functions should be your first point of call.
Depends: R(>= 3.1), methods, stats, zoo(>= 0.9-1)
Suggests: testthat
License: GPL
LazyLoad: yes
Packaged: 2016-10-04 12:36:29 UTC; killick
LazyData: true
Packaged: 2022-03-14 14:14:13 UTC; killick
NeedsCompilation: yes
Repository: CRAN
Date/Publication: 2022-03-14 15:50:02 UTC
Author: Rebecca Killick [aut, cre],
Kaylea Haynes [aut],
Idris Eckley [ths],
Paul Fearnhead [ctb, ths],
Jamie Lee [ctr]
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ exportMethods(plot,summary,show,nseg,logLik,likelihood,data.set,data.set.ts,cpts
method,ncpts,ncpts.max,param.est,param, coef,pen.type,pen.value,pen.value.full, minseglen, seg.len,"cpts<-","cpttype<-","data.set<-","distribution<-","test.stat<-","ncpts.max<-","param.est<-","pen.type<-",
"pen.value<-", "method<-", "cpts.full<-", "minseglen<-","pen.value.full<-")

useDynLib(changepoint)
useDynLib(changepoint, .registration=TRUE)
15 changes: 15 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
Version 2.2.3
=============
* Updated documentation to reflect that the changepoint is the last observation of a segment, not the first observation of a new segment as previously described. Thanks to Alex Bertram for reporting this.
* Added fuctionality for cpt.range into cpts to allow specification of ncpts. Use as cpts(object,ncpts=X) to retrive the X changepoints segmentation from object which has a cpt.range class. Thanks to Craig Faunce for the suggestion.
* Corrected parameter estimation for cpt.reg class so that sig2 contains the variance MLE per segment. This addresses a consistency issue with lm when evaluating logLik when no changepoints are found. Thanks to Simon Taylor for spotting this.
* Correction bug in parameter estimation for cpt.var with cpt.range class when ncpts!=NA. Previously this was using seg.len() function which returned NA for CROPS and incorrect segments lengths for BinSeg. Thanks to David Krider for asking a question which led to this bug being identified.
* Added "type=" functionality to the "diagnostic=TRUE" graphs. Thanks go to github user hoxo_m for providing the code and tests for this.
* Fixed bug that meant logLik(.) was erroring when used on output from cpt.mean(.).
* Updated changepoint package to new CRAN regulations.
* Updated JStatSoft web link in citation file.
* Changed bugreports field in Description to Github issues page.
* Removed a feature from the direct call to "segnigh.XX.YY" functions where a vector of penalties could be supplied. This caused a warning to occur in a dependency.
* Re-evaluated the maximum Q that could be given to all segneigh functions. Thanks to Aaron Lowther for highlighting.


Version 2.2.2
=============
* Updated R dependency, thanks to Mateusz Konieczny to identifying the problem (and solution).
Expand Down
2 changes: 1 addition & 1 deletion R/BinSeg_one_func_minseglen.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ BINSEG = function(sumstat, pen = 0, cost_func = "norm.mean", shape = 1, minsegle

n=length(sumstat[,1])-1
if(n<2){stop('Data must have atleast 2 observations to fit a changepoint model.')}
if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',floor(n/2)+1))}
if(Q<=0){stop(paste('Q is the maximum number of changepoints so should be greater than 0'))}

storage.mode(sumstat) = 'double'
Expand Down
2 changes: 1 addition & 1 deletion R/PELT_one_func_minseglen.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ PELT = function(sumstat,pen=0, cost_func = "norm.mean", shape = 1, minseglen = 1
storage.mode(numchangecpts) = 'integer'

# answer=.C('PELT',cost_func, y3, y2,y,as.integer(n),as.double(pen),cptsout,as.integer(error),as.double(shape))
answer=.C('PELT',cost_func, sumstat,as.integer(n),as.double(pen),cptsout,as.integer(error),as.double(shape), as.integer(minseglen), lastchangelike, lastchangecpts,numchangecpts)
answer=.C('PELTC',cost_func, sumstat,as.integer(n),as.double(pen),cptsout,as.integer(error),as.double(shape), as.integer(minseglen), lastchangelike, lastchangecpts,numchangecpts)

if(answer[[6]]>0){
stop("C code error:",answer[[6]],call.=F)
Expand Down
5 changes: 3 additions & 2 deletions R/cpt.class.R
Original file line number Diff line number Diff line change
Expand Up @@ -523,12 +523,13 @@

setMethod("param", "cpt.range", function(object,ncpts=NA,shape,...) {
if(is.na(ncpts)){
cpts=c(0,object@cpts)
cpts=object@cpts
if(cpts[1]!=0){cpts=c(0,cpts)} # PELT derivatives don't include the 0
}
else{
ncpts.full=apply(cpts.full(object),1,function(x){sum(x>0,na.rm=TRUE)})
row=try(which(ncpts.full==ncpts),silent=TRUE)
if(class(row)=='try-error'){
if(inherits(row,'try-error')){
stop("Your input object doesn't have a segmentation with the requested number of changepoints.")
}
cpts=c(0,cpts.full(object)[row,1:ncpts],length(data.set(object)))
Expand Down
13 changes: 6 additions & 7 deletions R/exp.R
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ segneigh.meanvar.exp=function(data,Q=5,pen=0){
if(sum(data<=0)>0){stop('Exponential test statistic requires positive data')}
n=length(data)
if(n<4){stop('Data must have atleast 4 observations to fit a changepoint model.')}
if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>(n-2)){stop(paste('Q is larger than the maximum number of segments',n-2))}
all.seg=matrix(0,ncol=n,nrow=n)
for(i in 1:n){
sumx=0
Expand Down Expand Up @@ -193,14 +195,11 @@ segneigh.meanvar.exp=function(data,Q=5,pen=0){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}

if(op.cps==0){cpts=n}
Expand Down
11 changes: 5 additions & 6 deletions R/gamma.R
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ segneigh.meanvar.gamma=function(data,shape=1,Q=5,pen=0){

n=length(data)
if(n<4){stop('Data must have atleast 4 observations to fit a changepoint model.')}
if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>(n-2)){stop(paste('Q is larger than the maximum number of segments',n-2))}
all.seg=matrix(0,ncol=n,nrow=n)
for(i in 1:n){
sumx=0
Expand Down Expand Up @@ -185,14 +187,11 @@ segneigh.meanvar.gamma=function(data,shape=1,Q=5,pen=0){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}

if(op.cps==0){cpts=n}
Expand Down
6 changes: 5 additions & 1 deletion R/multiple.nonparametric.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
segneigh.var.css=function(data,Q=5,pen=0){
n=length(data)
if(n<4){stop('Data must have atleast 4 observations to fit a changepoint model.')}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}

y2=c(0,cumsum(data^2))
Expand Down Expand Up @@ -182,7 +184,9 @@ multiple.var.css=function(data,mul.method="BinSeg",penalty="MBIC",pen.value=0,Q=
segneigh.mean.cusum=function(data,Q=5,pen=0){
n=length(data)
if(n<2){stop('Data must have atleast 2 observations to fit a changepoint model.')}
if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>(n-2)){stop(paste('Q is larger than the maximum number of segments',n-2))}

y=c(0,cumsum(data))
oldmax=1000
Expand Down
32 changes: 13 additions & 19 deletions R/multiple.norm.R
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
segneigh.var.norm=function(data,Q=5,pen=0,know.mean=FALSE,mu=NA){
n=length(data)
if(n<4){stop('Data must have atleast 4 observations to fit a changepoint model.')}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if((know.mean==FALSE)&(is.na(mu))){
Expand Down Expand Up @@ -214,14 +215,11 @@ segneigh.var.norm=function(data,Q=5,pen=0,know.mean=FALSE,mu=NA){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}

if(op.cps==0){cpts=n}
Expand All @@ -234,8 +232,9 @@ segneigh.var.norm=function(data,Q=5,pen=0,know.mean=FALSE,mu=NA){
segneigh.mean.norm=function(data,Q=5,pen=0){
n=length(data)
if(n<2){stop('Data must have atleast 2 observations to fit a changepoint model.')}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
if(Q>(n-2)){stop(paste('Q is larger than the maximum number of segments',n-2))}
all.seg=matrix(0,ncol=n,nrow=n)
for(i in 1:n){
ssq=0
Expand Down Expand Up @@ -268,14 +267,11 @@ segneigh.mean.norm=function(data,Q=5,pen=0){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}
if(op.cps==0){cpts=n}
else{cpts=c(sort(cps.Q[op.cps+1,][cps.Q[op.cps+1,]>0]),n)}
Expand All @@ -287,6 +283,7 @@ segneigh.mean.norm=function(data,Q=5,pen=0){
segneigh.meanvar.norm=function(data,Q=5,pen=0){
n=length(data)
if(n<4){stop('Data must have atleast 4 observations to fit a changepoint model.')}
if(length(pen)>1){stop("Penalty must be a single value and not a vector")}

if(Q>((n/2)+1)){stop(paste('Q is larger than the maximum number of segments',(n/2)+1))}
all.seg=matrix(0,ncol=n,nrow=n)
Expand Down Expand Up @@ -329,14 +326,11 @@ segneigh.meanvar.norm=function(data,Q=5,pen=0){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}

if(op.cps==0){cpts=n}
Expand Down
2 changes: 1 addition & 1 deletion R/penalty_decision.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ penalty_decision = function(penalty, pen.value, n, diffparam, asymcheck, method)
}
if((penalty=="Manual")&&(is.numeric(pen.value)==FALSE)){
pen.value=try(eval(parse(text=paste(pen.value))),silent=TRUE)
if(class(pen.value)=='try-error'){
if(inherits(pen.value,'try-error')){
stop('Your manual penalty cannot be evaluated')
}else{
pen.return=pen.value
Expand Down
9 changes: 3 additions & 6 deletions R/poisson.R
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,11 @@ segneigh.meanvar.poisson=function(data,Q=5,pen=0){
}
}

op.cps=NULL
k=0:(Q-1)

for(i in 1:length(pen)){
criterion=-2*like.Q[,n]+k*pen[i]

op.cps=c(op.cps,which(criterion==min(criterion,na.rm=T))-1)
}
criterion=-2*like.Q[,n]+k*pen
op.cps=which(criterion==min(criterion,na.rm=T))[1]-1

if(op.cps==(Q-1)){warning('The number of segments identified is Q, it is advised to increase Q to make sure changepoints have not been missed.')}
if(op.cps==0){cpts=n}
else{cpts=c(sort(cps.Q[op.cps+1,][cps.Q[op.cps+1,]>0]),n)}
Expand Down
3 changes: 1 addition & 2 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
f <- read.dcf(file.path(libname, pkgname, "DESCRIPTION"),
c("Version", "Date"))
packageStartupMessage('Successfully loaded changepoint package version ',
f[1,1],'\n NOTE: Predefined penalty values changed in version 2.2. Previous penalty values with a postfix 1 i.e. SIC1 are now without i.e. SIC ',
'and previous penalties without a postfix i.e. SIC are now with a postfix 0 i.e. SIC0. See NEWS and help files for further details.')
f[1,1],'\n See NEWS for details of changes.')
}
4 changes: 2 additions & 2 deletions inst/CITATION
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ bibentry(bibtype="article",
volume = "58",
number = "3",
pages = "1--19",
url = "http://www.jstatsoft.org/v58/i03/",
url = "https://www.jstatsoft.org/v58/i03/",
)

bibentry(bibtype="Manual",
title = "{changepoint}: An {R} package for changepoint analysis",
author = c(person("Rebecca", "Killick"),person("Kaylea", "Haynes"), person(c("Idris", "A."), "Eckley")),
year = year,
url = "http://CRAN.R-project.org/package=changepoint",
url = "https://CRAN.R-project.org/package=changepoint",
note = note,
)

Expand Down
4 changes: 2 additions & 2 deletions man/changepoint-package.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Implements various mainstream and specialised changepoint methods for finding si
\tabular{ll}{
Package: \tab changepoint\cr
Type: \tab Package\cr
Version: \tab 2.2.2 \cr
Date: \tab 2016-10-04\cr
Version: \tab 2.2.3 \cr
Date: \tab 2022-03-08\cr
License: \tab GPL\cr
LazyLoad: \tab yes\cr
}
Expand Down
4 changes: 2 additions & 2 deletions man/cpt.mean.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ param.estimates=TRUE,minseglen=1)
}
}
\details{
This function is used to find changes in mean for data using the test statistic specfified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the first observation of the new segment / regime.
This function is used to find changes in mean for data using the test statistic specfified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the last observation of the segment / regime.
}
\value{
If \code{class=TRUE} then an object of S4 class "cpt" is returned. The slot \code{cpts} contains the changepoints that are returned. For \code{class=FALSE} the structure is as follows.
Expand Down Expand Up @@ -92,7 +92,7 @@ Rebecca Killick
set.seed(1)
x=c(rnorm(100,0,1),rnorm(100,10,1))
cpt.mean(x,penalty="SIC",method="AMOC",class=FALSE) # returns 100 to show that the null hypothesis
#was rejected and the change in mean is at 100
#was rejected and the change in mean is at 100 and the confidence level is 1.
ans=cpt.mean(x,penalty="Asymptotic",pen.value=0.01,method="AMOC")
cpts(ans)# returns 100 to show that the null hypothesis was rejected, the change in mean is at 100
#and we are 99% confident of this result
Expand Down
2 changes: 1 addition & 1 deletion man/cpt.meanvar.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class=TRUE,param.estimates=TRUE,shape=1,minseglen=2)
}
}
\details{
This function is used to find changes in mean and variance for data using the test statistic specified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the first observation of the new segment / regime.
This function is used to find changes in mean and variance for data using the test statistic specified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the last observation of the segment / regime.
}
\value{
If \code{class=TRUE} then an object of S4 class "cpt" is returned. The slot \code{cpts} contains the changepoints that are returned. For \code{class=FALSE} the structure is as follows.
Expand Down
2 changes: 1 addition & 1 deletion man/cpt.var.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test.stat="Normal",class=TRUE,param.estimates=TRUE,minseglen=2)
}
}
\details{
This function is used to find changes in variance for data using the test statistic specified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the first observation of the new segment / regime.
This function is used to find changes in variance for data using the test statistic specified in the test.stat parameter. The changes are found using the method supplied which can be single changepoint (AMOC) or multiple changepoints using exact (PELT or SegNeigh) or approximate (BinSeg) methods. A changepoint is denoted as the last observation of the segment / regime.
Note that for the test.stat="CSS" option the preset penalties are log(.) to allow comparison with test.stat="Normal".
}
\value{
Expand Down
2 changes: 1 addition & 1 deletion src/PELT_one_func_minseglen.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void FreePELT(error)
}
}

void PELT(cost_func, sumstat,n,pen,cptsout,error, shape, minseglen, lastchangelike, lastchangecpts, numchangecpts)
void PELTC(cost_func, sumstat,n,pen,cptsout,error, shape, minseglen, lastchangelike, lastchangecpts, numchangecpts)
char **cost_func;
double *sumstat; /* Summary statistic for the time series */
int *n; /* Length of the time series */
Expand Down
25 changes: 25 additions & 0 deletions src/changepoint_init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdlib.h> // for NULL
#include <R_ext/Rdynload.h>

/* FIXME:
Check these declarations against the C/Fortran source code.
*/

/* .C calls */
extern void binseg(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
extern void FreePELT(void *);
extern void PELTC(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);

static const R_CMethodDef CEntries[] = {
{"binseg", (DL_FUNC) &binseg, 10},
{"FreePELT", (DL_FUNC) &FreePELT, 1},
{"PELTC", (DL_FUNC) &PELTC, 11},
{NULL, NULL, 0}
};

void R_init_changepoint(DllInfo *dll)
{
R_registerRoutines(dll, CEntries, NULL, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}

0 comments on commit 7aacc73

Please sign in to comment.