2016-12-20 5 views
0

У меня есть DataFrame df1:биннинговых данных в равных размерах коробки и применить МНК для каждого бина

import pandas as pd 
import numpy as np 
import statsmodels.formula.api as sm 

df1 = pd.DataFrame(np.random.randn(3000,1), index= pd.date_range('1/1/1990', periods=3000), columns = {"M"}) 

Я хотел бы группировать элементы в размере коробки = 10, установите их с помощью МНК и вычислить Y_t, где Y_t обозначает ряд прямых линий.

Другими словами, я хотел бы взять первые 10 значений, поместив их с помощью OLS (Y_t = b * X_t + a_0) и получить значения Y_t для этих 10 значений. Снова сделайте то же самое для следующих 10 значений (не катящееся окно!) И т. Д. И т. Д.

Мой подход

Первый вопрос, который я столкнулся в том, что я не мог соответствовать элементы, используя DateTime значения в качестве предикторов, поэтому я определил новый DataFrame df_fit, который содержит две колонки A и B. Колонка A содержит целые числа от 0 до 9, и столбец B значения df1 в группах из 10 элементов:

def compute_yt(df,i,bs): 

    df_fit = pd.DataFrame({"B": np.arange(1,bs+1),\ 
          "A": df.reset_index().loc[i*bs:((i+1)*bs-1), "M"]}) 

    fit = sm.ols(formula = "A ~ B", data = df_fit).fit() 
    yt = fit.params.B*df_fit["B"] + fit.params.Intercept 

    return yt 

Где bs является размер коробки (10 в этом примере), i представляет собой индекс, который позволяет подметать по всем значениям.

Наконец,

result = [compute_yt(df1,n,l) for n in np.arange(0,round(len(df1)/l)-1)]   

result =  
     Name: B, dtype: float64, 840 -0.249590 
     841 -0.249935 
     842 -0.250280 
     843 -0.250625 
     844 -0.250970 
     845 -0.251315 
     846 -0.251660 
     847 -0.252005 
     848 -0.252350 
     849 -0.252695 
     Name: B, dtype: float64, 850 -0.252631 
     851 -0.252408 
     ... ... 

Где result это список, который должен содержать значения для прямой линии подходит.

Итак, мои вопросы заключаются в следующем:

  1. Есть ли способ запустить МНК, используя значения DateTime в качестве предсказателей?

  2. Я хотел бы использовать представление списка для построения DataFrame (с той же формой, что и df1), содержащей значения y_t. Это относится к вопросу (1) в том смысле, что я хотел бы получить временные ряды для этих значений.

  3. Есть ли более «питонический» способ написать этот код? То, как я нарезал DataFrame, кажется, не слишком подходит.

+0

на сегодняшний день вещи, очевидные варианты будут просто преобразовать в целое число 'astype (np.int64)' или использовать DT аксессор (например, 'dt.year') или комбинацию дт аксессорах. – JohnE

+0

Я не знаю, если это больше, чем питона, чем то, что вы сделали, но вы можете использовать 'pd.cut' или' pd.qcut' для binning. – JohnE

ответ

1

Не совсем уверен, если это то, что вы хотели сделать, но я первый добавил номер группы и номер наблюдения для каждой строки вашего dataframe, а затем поворачиваем его так, чтобы каждая строка имела 10 наблюдений.

df1 = pd.DataFrame(data={'M':np.random.randn(3000)}, index= pd.date_range('1/1/1990', periods=3000)) 

df1['group_num'] = np.repeat(range(300), 10) 
df1['obs_num'] = np.tile(range(10), 300) 

df_pivot = df1.pivot(index='group_num', columns='obs_num') 
print(df_pivot.head()) 

Выход

    M             \ 
obs_num   0   1   2   3   4   5 
group_num                
0   -0.063775 -1.293410 0.395011 -1.224491 1.777335 -2.395643 
1   -1.111679 1.668670 1.864227 -1.555251 0.959276 0.615344 
2   -0.213891 -0.733493 0.175590 0.561410 1.359565 -1.341193 
3   0.534735 -2.154626 -1.226191 -0.309502 1.368085 0.769155 
4   -0.611289 -0.545276 -1.924381 0.383596 0.322731 0.989450 


obs_num   6   7   8   9 
group_num           
0   -1.461194 -0.481617 -1.101098 1.102030 
1   -0.120995 -1.046757 1.286074 -0.832990 
2   0.322485 -0.825315 -2.277746 -0.619008 
3   0.794694 0.912190 -1.006603 0.572619 
4   -1.191902 1.229913 1.105221 0.899331 

Я тогда написал функцию, чтобы сделать обычный метод наименьших квадратов с statsmodels - не тип формулы.

import statsmodels.api as sm 
def compute_yt(row): 
    X = sm.add_constant(np.arange(10)) 
    fit = sm.OLS(row.values, X).fit() 
    yt = fit.params[1] * row.values + fit.params[0] 
    return yt 

Я тогда назвал эту функцию по всем строкам с помощью apply.

df_pivot.apply(compute_yt, axis=1) 

С выводом прогнозируемого значения для каждого исходного набора из 10 значений.

    M             \ 
obs_num   0   1   2   3   4   5 
group_num                
0   -0.063775 -1.293410 0.395011 -1.224491 1.777335 -2.395643 
1   -1.111679 1.668670 1.864227 -1.555251 0.959276 0.615344 
2   -0.213891 -0.733493 0.175590 0.561410 1.359565 -1.341193 
3   0.534735 -2.154626 -1.226191 -0.309502 1.368085 0.769155 
4   -0.611289 -0.545276 -1.924381 0.383596 0.322731 0.989450 


obs_num   6   7   8   9 
group_num           
0   -1.461194 -0.481617 -1.101098 1.102030 
1   -0.120995 -1.046757 1.286074 -0.832990 
2   0.322485 -0.825315 -2.277746 -0.619008 
3   0.794694 0.912190 -1.006603 0.572619 
4   -1.191902 1.229913 1.105221 0.899331 
+0

Большое спасибо за ваш ответ. Это определенно намного лучше, чем то, что я сделал –

Смежные вопросы