WITH x(v) AS (VALUES (1),(2),(NULL)) SELECT l.v, r.v, l.v = r.v AS equality, l.v IS NOT DISTINCT FROM r.v AS isnotdistinctfrom FROM x l, x r;
Thanks to Sam Mason via the PostgreSQL - general mailing list.
Work-products and stray thoughts from the Land of Entrapment
WITH x(v) AS (VALUES (1),(2),(NULL)) SELECT l.v, r.v, l.v = r.v AS equality, l.v IS NOT DISTINCT FROM r.v AS isnotdistinctfrom FROM x l, x r;
## box-and-whisker plot of FFT power spectrum by frequency/period ## vary these parameters -- r as per logistic map ## see http://en.wikipedia.org/wiki/Logistic_map for details logmap = function(n, r, x0=0.5) { ret = rep(x0,n) for (ii in 2:n) { ret[ii] = r*ret[ii-1]*(1-ret[ii-1]) } return(ret) } ## modify these for interesting behavior differences rfrom = 3.4 rto = 3.7 rsteps=200 seqlen=1e4 require(plyr) require(ggplot2) mytimeseries = aaply(seq(from=rfrom, to=rto, length.out=rsteps), 1, function(x) { logmap(seqlen, x) }) ## you can plug in any array here for mytimeseries ## each row is a timeseries ## for series by column, change the margin from 1 to 2, below logspec = adply( mytimeseries, 1, function(x) { ## change spec.pgram parameters as per goals ret = spectrum(x, taper=0, demean=T, pad=0, fast=T, plot=F) return( data.frame(freq=ret$freq, spec=ret$spec)) }) ## boxplot stats at each unique frequency logspec.bw = ddply(logspec, 'freq', function(x) { ret = boxplot.stats(log10(x$spec)); ## sometimes $out is empty, bind NA to keep dimensions correct return(data.frame(t(10^ret$stats), out=c(NA,10^ret$out))) }) ## plot -- outliers are dots ## be careful with spacing of hard returns -- ggplot has odd rules ## as close to default "spectrum" plot as possible ggplot(logspec.bw, aes(x=1/(freq))) + geom_ribbon(aes(ymin=X1, ymax=X5), alpha=0.35, fill='green') + geom_ribbon(aes(ymin=X2, ymax=X4), alpha=0.5, fill='blue') + geom_line(aes(y=X3)) + geom_point(aes(y=out), color='darkred') + scale_x_continuous( trans=c('inverse'), name='Period') + scale_y_continuous(name='Power', trans='log10')
require(animation) saveVideo({ ani.options(interval = 1/5, ani.type='png', ani.width=1600, ani.height=1200) for (ii in c(seq(from=3.2, to=3.5, length.out=200), seq(from=3.5, to=4, length.out=1200))) { spectrum(logmap(1e4, ii), taper=0, demean=T, pad=0, fast=T, sub=round(ii, 3)) } }, video.name = "logmap2.mp4", other.opts = "-b 600k")
## using R -- ## logistic map function: logmap = function(n, r, x0=0.5) { ret = rep(x0,n) for (ii in 2:n) { ret[ii] = r*ret[ii-1]*(1-ret[ii-1]) } return(ret) } ## compare: spectrum(logmap(1e5, 3.5), main='R tapers to 0.1 by default') spectrum(logmap(1e5, 3.5), taper=0, main='No taper') spectrum(logmap(1e5+1, 3.5), taper=0, main='Non-composite length, fast=T pads by default') spectrum(logmap(1e5, 3.5), taper=0.5, sub='Lots of padding approximately recovers "correct" results')