Как рассчитать coskew и cokurtosis

Вы можете рассчитать перекос и эксцесс с помощью методов

Однако нет удобного способа вычисления coskew или cokurtosis между переменными. Или, что еще лучше, матрица coskew или cokurtosis.


Рассмотрим pd.DataFrame df

import pandas as pd
import numpy as np

np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(10, 2), columns=list('ab'))

df

          a         b
0  0.444939  0.407554
1  0.460148  0.465239
2  0.462691  0.016545
3  0.850445  0.817744
4  0.777962  0.757983
5  0.934829  0.831104
6  0.879891  0.926879
7  0.721535  0.117642
8  0.145906  0.199844
9  0.437564  0.100702

Как рассчитать coskew и cokurtosis a и b?

Ответ 1

Ссылки

Вычисление coskew

Моя интерпретация coskew является "корреляцией" между одной серией и дисперсией другой. Таким образом, вы можете фактически иметь два типа coskew, в зависимости от того, какую серию мы вычисляем. Википедия показывает эти две формулы

'left'
введите описание изображения здесь
'right'
введите описание изображения здесь

К счастью, когда мы вычисляем матрицу coskew, одна является транспонированной другой.

def coskew(df, bias=False):
    v = df.values
    s1 = sigma = v.std(0, keepdims=True)
    means = v.mean(0, keepdims=True)

    # means is 1 x n (n is number of columns
    # this difference broacasts appropriately
    v1 = v - means

    s2 = sigma ** 2

    v2 = v1 ** 2

    m = v.shape[0]

    skew = pd.DataFrame(v2.T.dot(v1) / s2.T.dot(s1) / m, df.columns, df.columns)

    if not bias:
        skew *= ((m - 1) * m) ** .5 / (m - 2)

    return skew

демонстрация

coskew(df)

          a         b
a -0.369380  0.096974
b  0.325311  0.067020

Мы можем сравнить это с df.skew() и проверить, что диагонали одинаковы

df.skew()

a   -0.36938
b    0.06702
dtype: float64

Вычисление cokurtosis

Моя интерпретация кокуроза является одной из двух

  • "корреляция" между серией и перекосом другого
  • "корреляция" между дисперсиями двух серий

Для варианта 1. мы снова имеем как левый, так и правый варианты, которые в матричной форме переносятся друг на друга. Итак, мы сосредоточимся только на левом варианте. Это дает нам возможность вычислить в общей сложности два варианта.

'left'
введите описание изображения здесь
'middle'
введите описание изображения здесь

def cokurt(df, bias=False, fisher=True, variant='middle'):
    v = df.values
    s1 = sigma = v.std(0, keepdims=True)
    means = v.mean(0, keepdims=True)

    # means is 1 x n (n is number of columns
    # this difference broacasts appropriately
    v1 = v - means

    s2 = sigma ** 2
    s3 = sigma ** 3

    v2 = v1 ** 2
    v3 = v1 ** 3

    m = v.shape[0]

    if variant in ['left', 'right']:
        kurt = pd.DataFrame(v3.T.dot(v1) / s3.T.dot(s1) / m, df.columns, df.columns)
        if variant == 'right':
            kurt = kurt.T
    elif variant == 'middle':
        kurt = pd.DataFrame(v2.T.dot(v2) / s2.T.dot(s2) / m, df.columns, df.columns)

    if not bias:
        kurt = kurt * (m ** 2 - 1) / (m - 2) / (m - 3) - 3 * (m - 1) ** 2 / (m - 2) / (m - 3)
    if not fisher:
        kurt += 3

    return kurt

демонстрация

cokurt(df, variant='middle', bias=False, fisher=False)

          a        b
a  1.882817  0.86649
b  0.866490  1.63200

cokurt(df, variant='left', bias=False, fisher=False)

          a        b
a  1.882817  0.19175
b -0.020567  1.63200

Диагональ должна быть равна kurtosis

df.kurtosis() + 3

a    1.882817
b    1.632000
dtype: float64