Я был мотивирован использовать функцию pandas rolling
для выполнения скользящей многофакторной регрессии (этот вопрос НЕ о скользящей многофакторной регрессии). Я ожидал, что после df.rolling(2)
я смогу использовать apply
и возьму полученный pd.DataFrame
извлечение ndarray с помощью .values
и выполнить требуемое умножение матрицы. Это не получилось.
Вот что я нашел:
import pandas as pd
import numpy as np
np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(5, 2).round(2), columns=['A', 'B'])
X = np.random.rand(2, 1).round(2)
Как выглядят объекты:
print "\ndf = \n", df
print "\nX = \n", X
print "\ndf.shape =", df.shape, ", X.shape =", X.shape
df =
A B
0 0.44 0.41
1 0.46 0.47
2 0.46 0.02
3 0.85 0.82
4 0.78 0.76
X =
[[ 0.93]
[ 0.83]]
df.shape = (5, 2) , X.shape = (2L, 1L)
Матричное умножение ведет себя нормально:
df.values.dot(X)
array([[ 0.7495],
[ 0.8179],
[ 0.4444],
[ 1.4711],
[ 1.3562]])
Использование применить для выполнения строки по строке. Точечный продукт ведет себя как ожидалось:
df.apply(lambda x: x.values.dot(X)[0], axis=1)
0 0.7495
1 0.8179
2 0.4444
3 1.4711
4 1.3562
dtype: float64
Groupby → Apply ведет себя так, как я ожидал:
df.groupby(level=0).apply(lambda x: x.values.dot(X)[0, 0])
0 0.7495
1 0.8179
2 0.4444
3 1.4711
4 1.3562
dtype: float64
Но когда я запускаю:
df.rolling(1).apply(lambda x: x.values.dot(X))
Я получаю:
AttributeError: объект 'numpy.ndarray' не имеет атрибутов 'values'
Итак, pandas использует прямую ndarray
в своей реализации rolling
. Я могу справиться с этим. Вместо .values
, чтобы получить ndarray
, попробуйте:
df.rolling(1).apply(lambda x: x.dot(X))
фигуры (1,) и (2,1) не выровнены: 1 (dim 0)!= 2 (dim 0)
Подождите! Что?!
Итак, я создал пользовательскую функцию, чтобы посмотреть, что делает прокатка.
def print_type_sum(x):
print type(x), x.shape
return x.sum()
Затем выполнил:
print df.rolling(1).apply(print_type_sum)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
A B
0 0.44 0.41
1 0.46 0.47
2 0.46 0.02
3 0.85 0.82
4 0.78 0.76
В результате получается pd.DataFrame
то же самое, что хорошо. Но он напечатал 10 одномерных объектов ndarray
. Что насчет rolling(2)
print df.rolling(2).apply(print_type_sum)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
A B
0 NaN NaN
1 0.90 0.88
2 0.92 0.49
3 1.31 0.84
4 1.63 1.58
То же самое, ожидайте вывод, но он напечатал 8 ndarray
объектов. rolling
производит одиночный размер ndarray
длины window
для каждого столбца в отличие от ожидаемого, который был ndarray
формы (window, len(df.columns))
.
Вопрос: почему?
Теперь у меня нет возможности легко запускать многокомпонентную регрессию.