2
$\begingroup$

Suppose you have a record of distribution for each day in some period. For example, some distribution which depends on a parameter which evolves over time. Suppose we have dozens or hundreds of days. How would you visualize the change of this distribution? I want the plot to contain as much info as possible.

One way I could think of is: proxy the density function and plot these curves's evolution in 2D. It will be some form of homotopy: the initial distribution converging to the final with some smooth step. Of course here I assume smoothness.

Thanks for your help.

The question is theoretical in nature but I am aiming for python realization so implementations or suggestions for libraries are also welcome.

$\endgroup$
4
$\begingroup$

EDIT Didn't see it was a python question. I think the idea stands, but not sure if python implementation readily available.


You might want to look into so called ridge-plots using R package ggridges (and gganimate for animation). Below is an example (obviously doesn't have to be an animation):

enter image description here

Code is available in this gist.

$\endgroup$
2
$\begingroup$

Always think about the nature of your situation: Who will be the audience for this plot? What are my goals for it? What are my data?

You state that you have a "distribution which depends on a parameter which evolves over time". If your audience is fairly sophisticated, and this is a known, studied distribution (e.g., a Weibull), then you could estimate the changing parameter for each day, plot it on a scatterplot, and smooth it with something simple like a LOWESS line.

Here's an example. These are coded in R, but they are intended to be easy to follow by people who don't use R, and should be possible to translate to Python.

library(fitdistrplus)      # we'll use this package
set.seed(9234)             # this makes the example exactly reproducible

day = rep(1:16, each=100)  # 1 through 16, each repeated 100x
y   = c()                  # an empty vector to hold the data
for(i in 1:16){            # generates data from Weibull distributions w/ the
  y = c(y,                 #  shape parameter increasing (but decelerating) by day
        rweibull(n=100, shape=(.5 + .1*i - .002*(i^2)), scale=1))
}
# estimate Weibull shape & scale parameters by MLE for each day
d = t(sapply(split(y, day), function(x){ fitdist(x, distr="weibull")$estimate }))
d = data.frame(day=1:16, d)
d
#    day     shape     scale
# 1    1 0.6311143 0.9871380
# 2    2 0.7501392 1.0168905
# 3    3 0.7510426 0.8853516
# 4    4 0.8142484 0.8701132
# 5    5 0.9081937 1.1098466
# 6    6 0.9679144 1.0668120
# 7    7 1.0347746 1.0638731
# 8    8 1.1496184 0.9775989
# 9    9 1.1724681 1.0758072
# 10  10 1.2396152 0.9975250
# 11  11 1.2519313 0.8847656
# 12  12 1.4648643 1.0801915
# 13  13 1.3258313 0.9113326
# 14  14 1.4301392 0.9699252
# 15  15 1.5494493 1.0448072
# 16  16 1.5989056 1.0133831
windows()
  plot(shape~day, d)
  lines(lowess(d$day, d$shape), col="red")

enter image description here

If the data weren't from a known distribution, you could plot multiple lines tracing fixed quantiles over time.

dq = t(sapply(split(y, day), function(x){ quantile(x, probs=c(0.25, 0.5, 0.75, 0.95)) }))
dq = data.frame(day=1:16, dq)
names(dq) = c("day", "25%", "50%", "75%", "95%")
dq
#    day       25%       50%      75%
# 1    1 0.1447001 0.5212207 1.628061
# 2    2 0.2318992 0.6657878 1.394435
# 3    3 0.1868559 0.5122787 1.618891
# 4    4 0.1665822 0.6402280 1.259112
# 5    5 0.3038764 0.6778831 1.418966
# 6    6 0.2508331 0.7469482 1.447055
# 7    7 0.2759569 0.7411599 1.527585
# 8    8 0.2774774 0.7496496 1.421123
# 9    9 0.3630679 0.9203537 1.343523
# 10  10 0.3788195 0.6613015 1.263599
# 11  11 0.3514467 0.6411170 1.110531
# 12  12 0.4697239 0.8562416 1.253663
# 13  13 0.3281270 0.6732758 1.113507
# 14  14 0.4498140 0.7440592 1.143489
# 15  15 0.4391240 0.8440031 1.371128
# 16  16 0.4726235 0.8386493 1.210914
windows()
  plot(1,1, xlim=c(1,16), ylim=c(0, 7), xlab="day", ylab="value", type="n")
  lines(dq$day, dq$`25%`, col="red",    lty=2)
  lines(dq$day, dq$`50%`, col="black",  lty=1)
  lines(dq$day, dq$`75%`, col="blue",   lty=3)
  lines(dq$day, dq$`95%`, col="purple", lty=4)
  legend("topright", legend=c("95%", "75%", "50%", "25%"), lty=c(4,3,1,2),
         col=c("purple", "blue", "black", "red"))

enter image description here

If your audience won't be as sophisticated, and wouldn't know what a "Weibull" is or be thrown off by trying to follow the idea of the "75th percentile", and you want something with more pizzazz, make a panel of kernel density plots. (Admittedly, adibender's plot has more pizzazz than this.)

windows()
  par(mfrow=c(4,4))
  for(i in 1:16){
    plot(density(y[day==i]), main=paste("day", i), xlab="", xlim=range(y),
         ylim=c(0, .8), ylab="", axes=FALSE);  box()
  }

enter image description here

$\endgroup$
0
$\begingroup$

Assuming you have an empirical distribution for each day, as for example a store looking at total payment by each customer, per day. You can look upon this as a time series of histograms, and that could be plotted in various ways, maybe by a series of boxplots. If you have some example data we could try various options!

A similar question was asked&answered here: https://stackoverflow.com/questions/11690194/time-series-histogram

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.