После df.groupby.apply в sub-df, переданном в пользовательскую функцию, отсутствуют данные - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь получить коэффициент простой линейной регрессии. Трюки 1) это W-месячная скользящая регрессия 2) для каждого окна должно быть минимальное количество записей, даты которых не расходятся больше года.

Однако мой код ломается: после перехода к функции calc_beta переданный в нее df не имеет всех исходных столбцов. Я не могу прикрепить образец CSV-файла (форма 12 * 74). Но приложенное изображение показывает важную его часть (1 запас с данными за 12 месяцев, что означает, что он должен произвести только 1 бета в конце).


import pandas as pd
import numpy as np

# test_df is attached as csv
# 29639 PERMNO (stock identifier) only has 12 records but are consecutive in monthends (could produce 1 beta)

def calc_beta(df, indpt_var, dpt_vars):
    print("@@@@@@@@@@@[enter image description here][1]@@@@@@@INSIDE calc_beta function@@@@@@@@@@@@@@")
    print(df)
    print("the shape is:", df.shape)
    print("the columns are:", df.columns)
    print("the len of columns is:", len(df.columns))
    print("the indpt_var has dtype:", df[indpt_var].values.dtype)
    print("the independent var is", indpt_var)
    print("the dependent vars are", dpt_vars)

    X = np.hstack((np.ones((df.shape[0], 1)), df[dpt_vars].values.astype(float)))
    y = df[indpt_var].values.astype(float)
    coeffs = list(np.dot(np.linalg.inv(np.dot(X.T, X)), np.dot(X.T, y)))[1:]

    return {df["w_pos"].unique(): coeffs}


def monthend_check(df, w, min_w, direction):
    df.reset_index(inplace=True)
    achor_date = np.sort(df.monthend.values)[-1]

    if direction == "up":
        boundary_date = achor_date - relativedelta(months=w)
        check_result = (boundary_date <= df.monthend) & (df.monthend <= achor_date)
    else:
        boundary_date = achor_date + relativedelta(months=w)
        check_result = (achor_date <= df.monthend) & (df.monthend <= boundary_date)

    # if it fails the check, then return the w_pos
    if sum(check_result) < min_w:
        return int(df.w_pos.unique())


def rollx(df, w, min_w, user_func, *args, direction="up"):
    # create windows
    if direction == "up":
        paper_stack = np.dstack([df.values[i - w + 1:i + 1, ].T for i in range(w - 1, df.shape[0])]).T
        new_df = pd.DataFrame(paper_stack.reshape(-1, df.shape[1]))
        new_df.index = np.repeat(range(w - 1, df.shape[0]), w)
    else:
        paper_stack = np.dstack([df.values[i:i + w, ].T for i in range(df.shape[0] - w + 1)]).T
        new_df = pd.DataFrame(paper_stack.reshape(-1, df.shape[1]))
        new_df.index = np.repeat(range(df.shape[0] - w + 1), w)

    # admin adj. to the new_df
    new_df.columns = df.columns.tolist()
    new_df.reset_index(inplace=True)
    new_df.rename(columns={"index": "w_pos"}, inplace=True)

    # check whether it meets the min_w requirement within each window created (identified by "w_pos")
    nan_idx = list(new_df.groupby("w_pos").apply(monthend_check, w=w, min_w=min_w, direction=direction))

    # for the groups whose "w_pos" is NOT in nan_idx & df_safe is not empty, apply function
    df_safe = new_df.loc[(~new_df.w_pos.isin(nan_idx)),]

    print(">>before the check gate, df_safe is")
    print(df_safe)
    print("is current df_safe empty?", df_safe.empty)
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

    if not df_safe.empty:

        print(">> at the check gate, PERMNO", df_safe.PERMNO.unique(), "passed the check!")
        print(">> current w_pos are", df_safe.w_pos.unique())
        print(">> df_safe that passed the check is:")
        print(df_safe)

        calc_result = df_safe.groupby("w_pos").apply(user_func, args[0], args[1])
        # assuming first is indept_var, the second one is dept_vars
        print("the calc_result is", calc_result)
        print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    return np.nan


indpt_var = ["stk_exret"]
dpt_vars = ["mkt_exret", "SMB", "HML"]
add_vars = (indpt_var, dpt_vars)
test_df.groupby("PERMNO").apply(rollx, 12, 10, calc_beta, *add_vars)

Показано 3 ошибки:

return {df ["w_pos"]. Unique (): coeffs} TypeError: unhashable тип: 'numpy.ndarray'

KeyError: 'w_pos'

AttributeError: у объекта «DataFrame» нет атрибута «PERMNO»

...