Description Usage Arguments Details Value Author(s) References See Also Examples
Numeric interpolation is defined in the usual way:
xOut <- x*(1-proportion) + y*proportion
Character interpolation does linear interpolation
on the number of characters of x
and
y
. If length(proportion) == 1
,
interpolation is done on cumsum(nchar(.))
.
If length(proportion) > 1
, interpolation
is based on nchar
. In either case,
the interpolant is rounded to an integer number
of characters. Interp
then returns
substring(y, ...)
unless nchar(x)
>
nchar(y)
, when it returns
substring(x, ...)
.
Character interpolation is used in two cases: (1)
At least one of x
and y
is
character. (2) At least one of x
and
y
is neither logical, integer, numeric,
complex nor raw, and class(unclass(.))
is
either integer or character.
In all other cases, numeric interpolation is used.
NOTE: This seems to provide a relatively simple
default for what most people would want from
the six classes of atomic vectors (logical,
integer, numeric, complex, raw, and character)
and most other classes. For example,
class(unclass(factor))
is integer. The
second rule would apply to this converting it to
character. The coredata
of an
object of class zoo
could be most
anything, but this relatively simple rule would
deliver what most people want in most case. An
exception would be an object with integer
coredata. To handle this as numeric, a
Interp.zoo
function would have to be
written.
1 2 3 4 5 6 7 8 |
x, y |
two vectors of the same class or to be coerced to the same class. |
proportion |
A number or numeric vector assumed to be between 0 and 1. |
argnames |
a character vector of length 3 giving args |
message0 |
A character string to be passed with |
argsChk |
a list as returned by |
... |
optional arguments for |
Interp
is an S3 generic function to allow users to
easily modify the behavior to interpolate between special
classes of objects.
Interp
has two basic algorithms for "Numeric" and
"Character" interpolation.
The computations begin by calling InterpChkArgs
to dispose quickly of simple cases (e.g, x
or
y
missing
or length
0
or if proportion
is <= 0 or >= 1 or
missing
). It returns a list.
If the list contains a component named "xout",
Interp
returns that value with no further
computations.
Otherwise, the list returned by InterpChkArgs
includes components "algorithm", "x", "y", "proportion",
"pLength1" (defined below), "raw", and "outclass". The
"algorithm" component must be either "Numeric" or
"Character". That algoritm is then performed as
discussed below using arguments "x", "y", and
"proportion"; all three will have the same length. The
class of "x" and "y" will match the algorithm.
The list component "raw" is logical: TRUE
if
the output will be raw or such that
class(unclass(.))
of the output will be raw.
In that case, a "Numeric" interpolation will be
transformed back into "raw". "outclass" will either be a
list of attributes to apply to the output or NA. If a
list, "xout" will be added as component ".Data" to the
list "outclass" and then then processed as
do.call('structure', outclass)
to produce the
desired output.
These two basic algorithms ("Numeric" and "Character") are
the same if proportion
is missing or not numeric:
In that case Interp
throws an error.
We now consider "Character" first, because it's domain of applicability is easier to describe. The "Numeric" algorithm is used in all other cases
1. "CHARACTER"
* 1.1. The "CHARACTER" algorithem is used when at
least one of x
and y
is neither logical,
integer, numeric, complex nor raw and satisfies one
of the following two additional conditions:
** 1.1.1. Either x
or y
is character.
** 1.1.2. class(unclass(.))
for at least one
of x
and y
is either character or
integer.
NOTE: The strengths and weaknesses of 1.1.2 can be
seen in considering factors and integer vectors of
class zoo
: For both,
class(unclass(.))
is integer. For factors,
we want to use as.character(.)
. For zoo
objects with coredata
of class
integer, we would want to use numeric interpolation.
This is not allowed with the current code but could
be easily implemented by writing Interp.zoo
.
* 1.2. If either x
or y
is missing
or has length
0, the one that is
provided is returned unchanged.
* 1.3. Next determine the class of the output. This
depends on whether neither, one or both of x
and
y
have one of the six classes of atomic vectors
(logical, integer, numeric, complex, raw, character):
** 1.3.1. If both x
and y
have one of
the six atomic classes and one is character, return a
character object.
** 1.3.2. If only one of x
and y
have
an atomic class, return an object of the class of the
other.
** 1.3.3. If neither of x
nor y
have a
basic class, return an object with the class of
y
.
* 1.4. Set pLength1 <- (length(proportion) == 1)
:
** 1.4.1. If(pLength1) do the linear interpolation on
cumsum(nchar(.))
.
** 1.4.2. Else do the linear interpolation on
nchar
.
* 1.5. Next check x
, y
and proportion
for comparable lengths: If all have length 0, return
an object of the appropriate class. Otherwise, call
compareLengths(x, proportion)
,
compareLengths(y, proportion)
, and
compareLengths(x, y)
.
* 1.6. Extend x
, y
, and proportion
to
the length of the longest using rep
.
* 1.7. nchOut <- the number of characters to output using numeric interpolation and rounding the result to integer.
* 1.8. Return substring(y, 1, nchOut)
except
when the number of characters from x
exceed
those from y
, in which case return
substring(x, 1, nchOut)
. [NOTE: This meets the
naive end conditions that the number of characters matches
that of x
when proportion
is 0 and matches
that of y
when proportion
is 1. This can be
used to "erase" characters moving from one frame to the
next in a video. See the examples.
2. "NUMERIC"
* 2.1. Confirm that this does NOT satisfy the condition for the "Character" algorithm.
* 2.2. If either x
or y
is missing or
has length
0, return the one provided.
* 2.3. Next determine the class of the output. As for
"Character" described in section 1.3, this depends on
whether neither, one or both of x
and y
have
a basic class other than character (logical, integer,
numeric, complex, raw):
** 2.3.1. If proportion
<= 0, return x
unchanged. If proportion
>= 1, return y
unchanged.
** 2.3.2. If neither x
nor y
has a basic
class, return an object of class equal that of y
.
** 2.3.3. If exactly one of x
and y
does
not have a basic class, return an object of class
determined by class(unclass(.))
of the non-basic
argument.
** 2.3.4. When interpolating between two objects of class
raw, convert the interpoland back to class raw. Do this
even when 2.3.2 or 2.3.3 applies and
class(unclass(.))
of both x
and y
are of class raw.
* 2.4. Next check x
, y
and
proportion
for comparable lengths: If all have
length 0, return an object of the appropriate class.
Otherwise, call compareLengths(x, proportion)
,
compareLengths(y, proportion)
, and
compareLengths(x, y)
.
* 2.5. Compute the desired interpolation and convert it to the required class per step 2.3 above.
Interp
returns a vector whose class is described
in "* 1.3" and "* 2.3" in "Details" above.
InterpChkArgs
returns a list or throws an error
as described in "Details" above.
Spencer Graves
The
Writing R Extensions manual (available via
help.start()
) lists six different classes of
atomic vectors: logical
,
integer
, numeric
,
complex
, raw
and
character
. See also Wickham, Hadley (2014)
Advanced R, especially
Wickham
(2013, section on "Atomic vectors" in the chapter on
"Data structures").
Many other packages have functions with names like "interp",
"interp1", and "interpolate". Some do one-dimensional
interpolation. Others do two-dimensional interpolation.
Some offer different kinds of interpolation beyond linear.
At least one is a wrapper for approx
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | ##
## 1. numerics
##
# 1.1. standard
xNum <- interpChar(1:3, 4:5, (0:3)/4)
# answer
xN. <- c(1, 2.75, 3.5, 4)
all.equal(xNum, xN.)
# 1.2. with x but not y:
# return that vector with a warning
xN1 <- Interp(1:4, p=.5)
# answer
xN1. <- 1:4
all.equal(xN1, xN1.)
##
## 2. Single character vector
##
i.5 <- Interp(c('a', 'bc', 'def'), character(0), p=0.3)
# with y = NULL or character(0),
# Interp returns x
all.equal(i.5, c('a', 'bc', 'def'))
i.5b <- Interp('', c('a', 'bc', 'def'), p=0.3)
# Cumulative characters (length(proportion)=1):
# 0.3*(total 6 characters) = 1.2 characters
i.5. <- c('a', 'b', '')
all.equal(i.5b, i.5.)
##
## 3. Reverse character example
##
i.5c <- Interp(c('a', 'bc', 'def'), '', 0.3)
# check: 0.7*(total 6 characers) = 4.2 characters
i.5c. <- c('a', 'bc', 'd')
all.equal(i.5c, i.5c.)
##
## 4. More complicated example
##
xCh <- Interp('', c('Do it', 'with R.'),
c(0, .5, .9))
# answer
xCh. <- c('', 'with', 'Do i')
all.equal(xCh, xCh.)
##
## 5. Still more complicated
##
xC2 <- Interp(c('a', 'fabulous', 'bug'),
c('bigger or', 'just', 'big'),
c(.3, .3, 1) )
x.y.longer <- c('bigger or', 'fabulous', 'big')
# use y with ties
# nch smaller 1 4 3
# nch larger 9 8 3
# d.char 8, 4, 0
# prop .3, .7, 1
# prop*d.char 2.4, 2.8, 0
# smaller+p*d 3, 7, 3
xC2. <- c('big', 'fabulou', 'big')
all.equal(xC2, xC2.)
##
## 6. with one NULL
##
null1 <- Interp(NULL, 1, .3)
all.equal(null1, 1)
null2 <- Interp('abc', NULL, .3)
all.equal(null2, 'abc')
##
## 7. length=0
##
log0 <- interpChar(logical(0), 2, .6)
all.equal(log0, 1.2)
##
## 8. Date
##
Jan1.1980 <- as.Date('1980-01-01')
Jan1.1972i <- Interp(0, Jan1.1980, .2)
# check
Jan1.1972 <- as.Date('1972-01-01')
all.equal(Jan1.1972, round(Jan1.1972i))
##
## 9. POSIXct
##
Jan1.1980c <- as.POSIXct(Jan1.1980)
Jan1.1972ci <- Interp(0, Jan1.1980c, .2)
# check
Jan1.1972ct <- as.POSIXct(Jan1.1972)
abs(difftime(Jan1.1972ct, Jan1.1972ci,
units="days"))<0.5
|
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.