Original Post
I have a plot generated with a timeDate x and a continuous y. I would
like to jitter x value, but jitter does not work with a timeDate input.
The problem seems to arise when jitter checks if x is infinite. Does
anyone have a jitterDate function? Thanks for any help. I will be glad
to summarize to the list.
# trivial example
> timeDate(as.character(1:3))
[1] 01/01/1960 01:00:00.000 01/01/1960 02:00:00.000 01/01/1960
03:00:00.000
> jitter(timeDate(as.character(1:3)))
Problem in is.number(x) & !is.inf(x): length of longer operand (5)
should be a multiple of length of shorter (3)
Use traceback() to see the call stack
> is.number(timeDate(as.character(1:3)))
[1] F F F
> is.inf(timeDate(as.character(1:3)))
[1] F F F F F
> is.infinite(timeDate(as.character(1:3)))
[1] F F F F F
Answer Summary
I received answers from four people. All of the replies were useful
depending on your needs. Both Sundar's and Sam's worked well for me.
From Sundar Dorai-Raj
If all you need to do is jitter for plotting purposes, then the
following should work:
set.seed(1)
# generate data
n <- 5
x <- timeDate(as.character(1:n))
jx <- jitter(as.numeric(x))
z <- rnorm(n)
# determine x-limits
xlim <- range(jx)
# expand x-limits by 10%
xlim <- xlim + c(-1, 1) * 0.10 * diff(xlim)
# set up device
plot(x, z, type = "n", xlim = xlim)
# add points
points(jx, z, pch = 16, col = 2)
From Matt Austin
> x <- timeDate(as.character(1:4))
> unclass(x)
$.Data:
$.Data[[1]]:
[1] 0 0 0 0
$.Data[[2]]:
[1] 3600000 7200000 10800000 14400000
$.Data.names:
[1] "julian.day" "milliseconds"
$.Data.classes:
[1] "integer" "integer"
$format:
[1] "%02m/%02d/%Y %02H:%02M:%02S.%03N"
$time.zone:
[1] "GMT"
> x
[1] 01/01/1960 01:00:00.000 01/01/1960 02:00:00.000 01/01/1960
03:00:00.000
01/01/1960 04:00:00.000
> x@.Data[[2]] <- as.integer(jitter(x@.Data[[2]]))
> x
[1] 01/01/1960 00:57:17.353 01/01/1960 02:00:18.217 01/01/1960
03:00:00.184
01/01/1960 04:02:06.581
It's not anywhere near perfect. You might want to use runif()
instead of
jitter() or play around with the scale argument in jitter() to get
the right
amount of noise.
From Sam Buttrey
It's true that jitter() doesn't work, but you can add random noise
directly to a timeDate object if you'd like. Consider the following
function:
jitter.timeDaste <- function(x, sd = 1/24)
{
#
# Jitter timeDate data.
#
return(x + rnorm(length(x), sd = sd))
}
This particular function uses the Normal, but you can substitute
whatever you'd like. You'll need to think about precisely how much
jittering you want; I've chosen 1 hour = 1/24 day.
From Steve McKinney
Message 1
jitterDate <-
function(x,
ms.jitter = TRUE,
factor = ifelse(ms.jitter, 1000, 5),
shift = 0
)
{
if (ms.jitter) {
## Shift away from 0 if all milliseconds are 0.
if(all(x@.Data[[2]] == 0) && (shift < 1)) shift = 1000
## Jitter the millisecond component
x@.Data[[2]] <-
as.integer(pmin(60 * 60 * 24 * 1000,
pmax(0,
jitter(x@.Data[[2]] + shift,
factor = factor))))
} else {
## Jitter the julian day component
x@.Data[[1]] <-
as.integer(jitter(x@.Data[[1]], factor = factor))
}
return(x)
}
Examples of use:
> td <- timeDate(c("1/1/97", "2/1/97", "mar 1, 1997"))
> td
[1] 01/01/1997 02/01/1997 03/01/1997
> td@.Data
[[1]]:
[1] 13515 13546 13574
[[2]]:
[1] 0 0 0
> td1 <- jitterDate(td)
> td1
[1] 01/01/1997 02/01/1997 03/01/1997
> td1@.Data
[[1]]:
[1] 13515 13546 13574
[[2]]:
[1] 991 1003 997
> td2 <- jitterDate(td, ms=F)
> td2
[1] 01/01/1997 02/01/1997 02/23/1997
> td2@.Data
[[1]]:
[1] 13515 13546 13568
[[2]]:
[1] 0 0 0
Message 2
Note also that jitter() does work on timeDate
objects in S-PLUS 7. If you can upgrade
to S-PLUS 7, that is one way to solve the issue.
Message 3
Bill Dunlap has suggested what appears to be the
best solution, as he generally does!
The problem in jitter() as you note is the
is.infinite() check. Here is a copy of the
jitter function with that line of code replaced.
Note that this modified function may not handle
infinite quantities properly, so I don't recommend
overwriting the standard jitter function.
jitterDate <-
function(x, factor = 1)
{
if(length(x) == 0)
return(numeric(0))
## z <- diff(range(x[is.finite(x)]))
z <- diff(range(x, na.rm=T))
if(z == 0 || is.na(z))
z <- 1
z <- factor * (z/50)
x + runif(length(x), - z, z)
}
Thank you all,
Karen J Byron
BD
tel: 201-847-5923 fax: 201-847-5887
E-mail: karen_byron@bd.com Website:
www.bd.com
-----------------------------------------
*******************************************************************
IMPORTANT MESSAGE FOR RECIPIENTS IN THE U.S.A.: This message may
constitute an advertisement of a BD group's products or services or a
solicitation of interest in them. If this is such a message and you would
like to opt out of receiving future advertisements or solicitations from
this BD group, please forward this e-mail to optoutbygroup@bd.com.
******************************************************************* This
message (which includes any attachments) is intended only for the
designated recipient(s). It may contain confidential or proprietary
information and may be subject to the attorney-client privilege or other
confidentiality protections. If you are not a designated recipient, you
may not review, use, copy or distribute this message. If you receive this
in error, please notify the sender by reply e-mail and delete this message.
Thank you.
*******************************************************************
Corporate Headquarters Mailing Address: BD (Becton, Dickinson and Company)
1 Becton Drive Franklin Lakes, NJ 07417 U.S.A.
*******************************************************************
|