A classical solution is to apply a robust local smoother.
In his book EDA (Addison-Wesley 1977), John Tukey lays out principles and procedures based primarily on running local medians. When a median of an odd number $2k+1$ of data is computed, up to $k$ of those values may be extreme yet the median will be finite and well-defined.
Handling infinities is still problematic. If the infinities are intended to represent truly large numbers, then keep them as-is; but otherwise, they function as missing values. Handle them simply by leaving them out of the time series when smoothing it.
Below is an example using Tukey's 3RSSH smoother. This notation refers to performing running medians of three data repeatedly until nothing changes, then performing two "splitting" operations to handle strings of repeated values, followed by a "Hanning" step which performs a weighted running mean within a three-element window (thereby averaging out some of the blocky jumps that can be created by the running medians). It's efficient and in practice works reasonably well for exploring data.
To see how well any smoother works, explore the residuals: these, by definition, are the differences between the data and their smoothed values. When residuals show local trends, you can go further by smoothing the residuals. Tukey provides the details and many worked examples.
This dataset was created to look like the first plot in the question. Then the values were replaced by "infinity" at ten randomly selected times. These couldn't be plotted at the left, so they show up as gaps in the graph. At the right, their positions are filled with orange crosses to confirm these data haven't been overlooked.
These computations are partially implemented in the base R
program within its smooth
function. Hanning is straightforward to code as a convolution. Additional code is needed to identify and skip over the infinite values. Here is the resulting implementation:
s <- function(x) {
hann <- function(x) {
n <- length(x)
x <- c(x[1], x, x[n])
convolve(x, c(1,2,1)/4, type="filter")
}
#
# Smooth the non-infinite, non-missing values of `x`.
#
y <- x
i <- which(!is.infinite(x) & !is.na(x))
y[i] <- hann(smooth(x[i], "3RSS"))
y
}
Long ago, I shared an Excel macro to implement all of Tukey's smoothers. (It goes well beyond the R
implementation.) It probably needs porting to newer versions of Excel, but the underlying code ought to work still. Google 'Tukey EDA Excel' to find it.