質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

0回答

2112閲覧

単回帰・重回帰解析に時間がかかりすぎてしまう

Taka787

総合スコア23

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2020/03/26 04:02

編集2020/03/26 05:52

実現したいこと

説明変数に効果があるかどうかの解析を行いたくコードを実行していますが、説明変数リストが500個以上あり、実行終了に2時間以上かかっても終わりませんでした。具体的には、del_non_effective_explanatory_variable関数以降の処理が2時間以上経過しても終了しません。もっと高速に処理できる方法をご存じでしたら教えていただきたいです。
実行方法は以下のpythonファイルを実行します
※他にsql_select.pyとsql.pyというファイルが関係しているのですが、文字制限で添付不可

Python

1""" 2「タイトルの特徴」のPVに対する寄与度を回帰分析によって求める。 3本モジュールにはビジネスロジックを記述。 4目的変数Y = pv, facebookからのpv等 5説明変数X = 「特定キーワードを含む」場合1、その他0 etc 6単回帰分析で効果のある特徴を絞り込み→相関係数が高い特徴を削除→重回帰分析で効果検証。 7""" 8from builtins import float 9 10import psycopg2 11from pandas import read_sql 12from pandas.core.series import Series 13from pandas.core.frame import DataFrame 14from statsmodels.api import add_constant 15from statsmodels.api import OLS 16from sql import make_sql 17import sql_select 18 19#以下DB接続情報 20DB_HOST = '***' 21DB_NAME = '***' 22DB_PORT = '***' 23DB_USER = '***' 24DB_PSWD = '***' 25 26MAX_P = 0.1 # P値。この値より小さい場合を有意と認める上限値 27MIN_BETA = 0.05 # 回帰係数。この値より絶対値が大きい場合を効果ありと認める 28MAX_COR = 0.3 # 相関係数。この値より値が大きい場合を正相関ありとして片方の説明変数を除外する 29 30 31def output_result(xs: list) -> None: 32 """ 33 各説明変数ごとの該当数、回帰係数、P値、効果判定、増加率を標準出力。 34 35 @param xs: 説明変数情報リスト 36 """ 37 for x in xs: 38 print("{}\t{}\t{}\t{}\t{}\t{}".format(x["NAME"], x["COUNT"], x["BETA"], 39 x["P"], x["EFFECT"], x["RATE_OF_INCREASE"])) 40 41 42def ols_simple(y_data: Series, x_data: Series) -> tuple: 43 """ 44 単回帰分析を行い、該当件数と回帰係数とP値を求めてタプルにして返す。 45 46 @param y_data: 目的変数データ 47 @param x_data: 説明変数データ 48 @return: (該当件数, 回帰係数(β), P値(P)) 49 """ 50 num_match = list(x_data).count(1) # 該当数 51 52 x_data = add_constant(x_data, prepend=False) # 説明変数に定数項を加える 53 results = OLS(y_data, x_data).fit() # (Ordinary Least Squares: 最小二乗法) 54 55 for beta_value, p_value in zip(results.params.to_dict().items(), results.pvalues.to_dict().items()): 56 if beta_value[0] == p_value[0] and p_value[0] != "const": 57 return num_match, beta_value[1], p_value[1] 58 59 """ 60 単回帰分析の結果から説明変数の効果判定を行い、不要なものを削除した 61 DataFrame(df)と説明変数リスト(xs)を返す。 62 xs内のdictにはkeyとしてCOUNT, BETA, P, RATE_OF_INCREASE, EFFECTが追加される。 63 64 @param df: DataFrame 65 @param y_name: 目的変数データ名 66 @param xs: 説明変数情報リスト 67 @return: (修正されたdf, 修正されたxs) 68 """ 69 70def del_non_effective_explanatory_variable(df: DataFrame, y_name: str, xs: list) -> tuple: 71 df_tmp = df.copy() 72 xs_tmp = list(xs) 73 74 del_xs = [] # 効果がないので削除するxsの部分list 75 for x in xs_tmp: 76 count, beta, p = ols_simple(df[y_name], df_tmp[x["AS"]]) 77 x["COUNT"] = count 78 x["BETA"] = beta 79 x["P"] = p 80 x["RATE_OF_INCREASE"] = 10 ** x["BETA"] - 1 81 if x["P"] < MAX_P and x["BETA"] > MIN_BETA: 82 x["EFFECT"] = " +" 83 elif x["P"] < MAX_P and x["BETA"] < -MIN_BETA: 84 x["EFFECT"] = " -" 85 else: 86 x["EFFECT"] = "" 87 del_xs.append(x) 88 89 output_result(xs_tmp) 90 for dx in del_xs: 91 print("{} は効果がありません".format(dx["NAME"])) 92 del(df_tmp[dx["AS"]]) 93 xs_tmp.remove(dx) 94 return df_tmp, xs_tmp 95 96 97def del_high_corr_explanatory_variable(df: DataFrame, y_name: str, xs: list) -> tuple: 98 """ 99 説明変数どうしの相関係数をチェックして、MAX_COR以上の場合は片方を削除した 100 DataFrame(df)と説明変数リスト(xs)を返す。 101 Pが小さいを優先。|β|が大きいを第二優先。 102 103 @param df: DataFrame 104 @param y_name: 目的変数データ名 105 @param xs: 説明変数情報リスト 106 @return: (修正されたdf, 修正されたxs) 107 """ 108 df_tmp = df.copy() 109 xs_tmp = list(xs) 110 111 del(df_tmp["id"]) 112 del(df_tmp["title"]) 113 del(df_tmp[y_name]) 114 del_xs = [] # 相関が高いので削除するxsの部分list 115 for i, x in enumerate(xs_tmp): 116 for j, x2 in enumerate(xs_tmp): 117 if i < j and df_tmp.corr()[x["AS"]][x2["AS"]] > MAX_COR and x not in del_xs and x2 not in del_xs: 118 if x["P"] > x2["P"]: # Pが小さい方残す 119 print("『{0}』と『{1}』の相関が高いので、『{0}』を削除します".format(x["NAME"], x2["NAME"])) 120 del_xs.append(x) 121 elif x["P"] < x2["P"]: 122 print("『{0}』と『{1}』の相関が高いので、『{0}』を削除します".format(x2["NAME"], x["NAME"])) 123 del_xs.append(x2) 124 else: 125 if abs(x["BETA"]) > abs(x2["BETA"]): # Pが同一なら|β|が大きい方を残す 126 print("『{0}』と『{1}』の相関が高いので、『{0}』を削除します".format(x2["NAME"], x["NAME"])) 127 del_xs.append(x2) 128 else: 129 print("『{0}』と『{1}』の相関が高いので、『{0}』を削除します".format(x["NAME"], x2["NAME"])) 130 del_xs.append(x) 131 132 df_tmp = df.copy() 133 for dx in del_xs: 134 del(df_tmp[dx["AS"]]) 135 xs_tmp.remove(dx) 136 return df_tmp, xs_tmp 137 138 139def ols_multiple(y_data: Series, x_data: DataFrame) -> list: 140 """ 141 重回帰分析を行い、回帰係数とP値を求めて、list((変数名, 回帰係数, P値))を返す。 142 143 @param y_data: 目的変数データ 144 @param x_data: 説明変数データ 145 @return: (変数名, 回帰係数(β), P値(P)) 146 """ 147 x_data = add_constant(x_data, prepend=False) # 説明変数に定数項を加える 148 results = OLS(y_data, x_data).fit() # (Ordinary Least Squares: 最小二乗法) 149 150 beta_p_values = [] 151 for beta_value, p_value in zip(results.params.to_dict().items(), results.pvalues.to_dict().items()): 152 if beta_value[0] == p_value[0] and p_value[0] != "const": 153 beta_p_values.append((p_value[0], beta_value[1], p_value[1])) 154 return beta_p_values 155 156 157def update_xs_with_ols_multiple(df: DataFrame, y_name: str, xs: list) -> list: 158 """ 159 重回帰分析の結果からxs内dictのkey=(COUNT, BETA, P, RATE_OF_INCREASE, EFFECT)を更新して 160 xsを返す。 161 162 @param df: DataFrame 163 @param y_name: 目的変数データ名 164 @param xs: 説明変数情報リスト 165 @return: 修正されたxs 166 """ 167 xs_tmp = list(xs) 168 x_data_name_list = [] # 説明変数データ識別名のリスト 169 for x in xs_tmp: 170 x_data_name_list.append(x["AS"]) 171 results = ols_multiple(df[y_name], df[x_data_name_list]) 172 # xs_tmpの更新 173 for result in results: 174 for x in xs_tmp: 175 if result[0] == x["AS"]: 176 x["BETA"] = result[1] 177 x["P"] = result[2] 178 x["RATE_OF_INCREASE"] = 10 ** x["BETA"] - 1 179 if x["P"] < MAX_P and x["BETA"] > MIN_BETA: 180 x["EFFECT"] = " +" 181 elif x["P"] < MAX_P and x["BETA"] < -MIN_BETA: 182 x["EFFECT"] = " -" 183 else: 184 x["EFFECT"] = "" 185 return xs_tmp 186 187# 188# main 189# 190ys = list(sql_select.ys) # 目的変数のlist ex. {"SELECT": "log(pv_1w.pv + 1)", "AS": "pv"} 191for y in ys: 192 y_name = y["AS"] 193 print("■■ 目的変数 = {} ■■".format(y_name)) 194 xs = list(sql_select.xs) # 説明変数のlist 195 sql = make_sql(y, xs) 196# print(sql) 197 198 # DB → DataFrame 199 with psycopg2.connect(host=DB_HOST, database=DB_NAME, port=DB_PORT, user=DB_USER, password=DB_PSWD) as conn: 200 df = read_sql(sql, conn) 201 df, xs = del_non_effective_explanatory_variable(df, y_name, xs) # 単回帰分析でdf, xsから効果のない説明変数と対応データを削除 202 print("\n-------------------------------------------") 203 print("■ 相関係数のチェック") 204 df, xs = del_high_corr_explanatory_variable(df, y_name, xs) # 相関関数をチェックしてdf, xsを更新 205 print("\n-------------------------------------------") 206 xs = update_xs_with_ols_multiple(df, y_name, xs) # 重回帰分析で得られた結果でxsを更新 207 print("■ 重回帰分析の結果") 208 output_result(xs) 209 print("\n\n=========================================")

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2020/03/26 05:45

どの処理にどの程度時間が掛かっているか位は追記されて方が良いかと思います。
Taka787

2020/03/26 05:52

ご指摘ありがとうございます。 情報追加しました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問