# Skewness/kurtosis

**URL:** <https://discourse.julialang.org/t/skewness-kurtosis/9652>\
**Category:** General Usage\
**Created:** [March 12, 2018, 1:09am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652 "2018-03-12T01:09:27Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [March 12, 2018, 1:09am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652/1 "2018-03-12T01:09:27Z")

</div>

Hi there. What am I missing? Skewness and kurtosis are different…

```julia
julia> using OnlineStats, StatsBase

julia> w = randn(10000);

julia> ws = Series(Mean(), Variance(), Moments());

julia> mean(w), var(w), skewness(w), kurtosis(w)
(0.004919317337882392, 0.9956975641666076, 0.005001290236278385, 0.022235410469709116)

julia> fit!(ws, w)
▦ Series{0}
│ EqualWeight | nobs=10000
├── Mean(0.00491932)
├── Variance(0.995698)
└── Moments([0.00491932, 0.995622, 0.0196614, 2.99593])

```

---

<div class="post-metadata">

**Author:** ![Yifan\_Liu](https://avatars.discourse-cdn.com/v4/letter/y/4da419/32.png) [@Yifan\_Liu](https://discourse.julialang.org/u/Yifan_Liu)\
**Post date:** [March 12, 2018, 1:19am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652/2 "2018-03-12T01:19:42Z")

</div>

My guess is that kurtosis calculates the excess kurtosis (from 3).

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [March 12, 2018, 2:28am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652/3 "2018-03-12T02:28:11Z")

</div>

I compared the results with R:

```nohighlight
> x <- fread("/tmp/rand10k.txt")$V1
> skewness(x, type=1)
[1] 0.00500129
> kurtosis(x, type=1)
[1] 0.02223541

```

Using Wikipedia’s definition of [standardized moments](https://en.wikipedia.org/wiki/Standardized_moment#Standard_normalization), I obtained the same results:

```julia
> y <- x - mean(x)
> sum(y^3)/10000 / (sum(y^2)/10000)^1.5
[1] 0.00500129
> sum(y^4)/10000 / (sum(y^2)/10000)^2 - 3
[1] 0.02223541

```

So indeed 0.02223541 is the excess kurtosis. OnlineStat’s kurtosis is approx. 3 apart so your observation is likely correct.

I still don’t understand what algorithm OnlineStats uses, however. Same question for skewness as there’s no _excess_ in skewness… I may just dive into the source code when I have time…

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [March 12, 2018, 3:51am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652/4 "2018-03-12T03:51:58Z")

</div>

[StatsBase documentation](https://juliastats.github.io/StatsBase.jl/latest/scalarstats.html#Moments-1) states that `skewness` computes the skewness à la [Joanes and Gill (1998)](https://dx.doi.org/10.1111/1467-9884.00122) type 1. This is similar to R’s

```julia
e1071::skewness(x, na.rm = FALSE, type = 1)

```

([Meyer et al. 2017](https://CRAN.R-project.org/package=e1071)) which by default uses `type = 3`.  
Similarly, for `kurtosis` the difference is that `e1071` uses `type = 3` by default and `StatsBase` computes `type = 1`.

I am unfamiliar with OnlineStats, but you can probably read the documentation to find out.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [March 12, 2018, 5:22am UTC](https://discourse.julialang.org/t/skewness-kurtosis/9652/5 "2018-03-12T05:22:38Z")

</div>

The following [comment in the code](https://github.com/joshday/OnlineStats.jl/blob/master/src/stats/stats.jl#L519) gives a hint that it does not represent the [central moment](https://en.wikipedia.org/wiki/Central_moment). It seems to be keeping tracking of moment about the origin (as opposed to moment about the mean.)

I found that OnlineStats provides `skewness` and `kurtosis` functions that take `Moments` as an argument, hence:

```julia
julia> ws.stats
(Mean(0.00491932), Variance(0.995698), Moments([0.00491932, 0.995622, 0.0196614, 2.99593]))

julia> skewness(ws.stats[3])
0.004999061081258352

julia> kurtosis(ws.stats[3])
0.02163099361000098

```

and the kurtosis matches the type-3 value from R.

```nohighlight
> skewness(x, type=3)
[1] 0.00500054
> kurtosis(x, type=3)
[1] 0.02163099

```

Skewness is still a little off. Following Wikipedia’s conversion formula:

\mu \_{3}=\mu '\_{3}-3\mu \mu '\_{2}+2\mu ^{3}

I can now match skewness exactly:

```julia
julia> function myskewness(o::Moments)
           v = value(o)
           (v[3] - 3.0 * v[1] * v[2] + 2 * v[1] ^ 3) / var(o) ^ 1.5
       end
myskewness (generic function with 1 method)

julia> myskewness(ws.stats[3])
0.005000540061498055

```

So it looks like it’s just an issue with with OnlineStats…
