2013-02-26 4 views
4

Pandas 0.8.1을 사용하고 있으며 현재 버전을 변경할 수 없습니다. 최신 버전이 아래의 문제를 해결하는 데 도움이된다면 답이 아닌 주석에 적어주십시오. 또한 이것은 리서치 복제 프로젝트를위한 것이기 때문에 하나의 새로운 데이터 포인트를 추가 한 후 회귀를 다시 실행해도 데이터 세트가 큰 경우 바보 일 수도 있지만 여전히해야합니다. 감사! 팬더에서Python Pandas를 사용한 누적 OLS

pandas.olswindow_type 인수에 rolling 옵션이 있지만이 창 크기 또는 기본값으로 전체 데이터 샘플의 사용의 몇 가지 선택이 필요하다는 암시 보인다. 나는 대신 모든 데이터를 누적 방식으로 사용하려고합니다.

날짜별로 정렬 된 pandas.DataFrame에서 회귀 분석을 실행하려고합니다. 각 인덱스 i에 대해 최소 날짜부터 인덱스 i까지의 데이터를 사용하여 회귀 분석을 실행하고 싶습니다. 창은 모든 반복마다 하나씩 효과적으로 증가하므로 모든 데이터가 초기 관측에서 누적 적으로 사용되며 창에서 데이터가 누락되지 않습니다.

나는이 기능을 수행하기 위해 apply과 작동하는 함수 (아래)를 작성했지만 받아 들일 수 없을 정도로 느립니다. 대신, pandas.ols을 사용하여 이러한 종류의 누적 회귀를 직접 수행 할 수 있습니까?

다음은 내 데이터에 대한 자세한 내용입니다. 나는 pandas.DataFrame 식별자의 열, 날짜 열, 왼쪽 값 열 및 오른쪽 값 열을 포함하고 있습니다. 식별자에 따라 그룹화하려면 groupby을 사용하고 왼쪽 및 오른쪽 변수로 구성된 모든 기간에 대해 누적 회귀를 수행합니다. 여기

내가 식별자 그룹화 된 객체에 apply와 함께 사용할 수 있어요 기능입니다 :

def cumulative_ols(
        data_frame, 
        lhs_column, 
        rhs_column, 
        date_column, 
        min_obs=60 
       ): 

    beta_dict = {} 
    for dt in data_frame[date_column].unique(): 
     cur_df = data_frame[data_frame[date_column] <= dt] 
     obs_count = cur_df[lhs_column].notnull().sum() 

     if min_obs <= obs_count: 
      beta = pandas.ols(
           y=cur_df[lhs_column], 
           x=cur_df[rhs_column], 
          ).beta.ix['x'] 
      ### 
     else: 
      beta = np.NaN 
     ### 
     beta_dict[dt] = beta 
    ### 

    beta_df = pandas.DataFrame(pandas.Series(beta_dict, name="FactorBeta")) 
    beta_df.index.name = date_column 
    return beta_df 
+0

당신은'pd.expanding_apply()'를 보셨습니까? – Zelazny7

+0

새 버전 인 것 같습니다.하지만 꼭 살펴 보겠습니다. 감사! – ely

+0

@EMS 업 그레 이드 할 수없는 경우를 대비하여 expanding_apply는 단지 구문 설탕입니다. rolling_apply를 지정하면 창 크기가 전체 집합의 길이이고 min_periods가 1 인 경우 동일한 확장 창 동작을 얻게됩니다. –

답변

0

주석의 조언에 따라, 나는 apply 어느 사용할 수 있습니다 내 자신의 기능을 생성 OLS 단 변량 회귀로부터 계수를 표현하기 위해 필요한 모든 개별적인 용어를 누적하기 위해 cumsum에 의존합니다.

def cumulative_ols(
        data_frame, 
        lhs_column, 
        rhs_column, 
        date_column, 
        min_obs=60, 
       ): 
    """ 
    Function to perform a cumulative OLS on a Pandas data frame. It is 
    meant to be used with `apply` after grouping the data frame by categories 
    and sorting by date, so that the regression below applies to the time 
    series of a single category's data and the use of `cumsum` will work  
    appropriately given sorted dates. It is also assumed that the date 
    conventions of the left-hand-side and right-hand-side variables have been 
    arranged by the user to match up with any lagging conventions needed. 

    This OLS is implicitly univariate and relies on the simplification to the 
    formula: 

    Cov(x,y) ~ (1/n)*sum(x*y) - (1/n)*sum(x)*(1/n)*sum(y) 
    Var(x) ~ (1/n)*sum(x^2) - ((1/n)*sum(x))^2 
    beta  ~ Cov(x,y)/Var(x) 

    and the code makes a further simplification be cancelling one factor 
    of (1/n). 

    Notes: one easy improvement is to change the date column to a generic sort 
    column since there's no special reason the regressions need to be time- 
    series specific. 
    """ 
    data_frame["xy"]   = (data_frame[lhs_column] * data_frame[rhs_column]).fillna(0.0) 
    data_frame["x2"]   = (data_frame[rhs_column]**2).fillna(0.0) 
    data_frame["yobs"]  = data_frame[lhs_column].notnull().map(int) 
    data_frame["xobs"]  = data_frame[rhs_column].notnull().map(int) 
    data_frame["cum_yobs"] = data_frame["yobs"].cumsum() 
    data_frame["cum_xobs"] = data_frame["xobs"].cumsum() 
    data_frame["cumsum_xy"] = data_frame["xy"].cumsum() 
    data_frame["cumsum_x2"] = data_frame["x2"].cumsum() 
    data_frame["cumsum_x"] = data_frame[rhs_column].fillna(0.0).cumsum() 
    data_frame["cumsum_y"] = data_frame[lhs_column].fillna(0.0).cumsum() 
    data_frame["cum_cov"] = data_frame["cumsum_xy"] - (1.0/data_frame["cum_yobs"])*data_frame["cumsum_x"]*data_frame["cumsum_y"] 
    data_frame["cum_x_var"] = data_frame["cumsum_x2"] - (1.0/data_frame["cum_xobs"])*(data_frame["cumsum_x"])**2 
    data_frame["FactorBeta"] = data_frame["cum_cov"]/data_frame["cum_x_var"] 
    data_frame["FactorBeta"][data_frame["cum_yobs"] < min_obs] = np.NaN 
    return data_frame[[date_column, "FactorBeta"]].set_index(date_column) 
### End cumulative_ols 

나는 이것이 나의 전 기능의 출력과 NumPy와의 linalg.lstsq 함수의 출력과 일치하는지 많은 테스트 케이스에 확인했습니다. 타이밍에 대한 완전한 벤치 마크를 수행하지는 못했지만, 일화 적으로, 내가 작업 한 경우는 약 50 배 더 빠릅니다.

관련 문제