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

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

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

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

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

Q&A

解決済

1回答

966閲覧

LinearRegressionを使い重回帰分析でt値を出したいのですが、一項目だけ正しくない値になってしまう。

yoshiringoo

総合スコア4

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

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

0グッド

1クリップ

投稿2023/03/23 05:44

編集2023/03/24 05:01

前提

djangoでゴルフのwebアプリを作っています。
その中で重回帰分析をしているのですが、一つの項目だけやたら大きい値になってしまいます。
エクセルやスプレッドシートでも重回帰分析をしてみたのですが、そちらでは正しい値になります。
Statモデルにスコア(目的変数)とパット数など(説明変数)があり、データベースに登録されたそれらの情報をもとに重回帰分析で影響度を計算しようとしています。

該当のソースコード

views.py

1df = pd.DataFrame(Stat.objects.filter(player_id=pk).values()) 2 df.columns = ["id", "player_id", "date", "total_score", "ob", "penalty", "fw", "par_on", "putt", "stat_number"] 3 x = df.drop(['id','player_id','date','total_score','stat_number'], axis=1) 4 y = df['total_score'] 5 6 reg = LinearRegression() 7 results = reg.fit(x,y) 8 coef = reg.coef_.round(4) 9 n = x.shape[0] 10 p = x.shape[1] 11 12 y_hat = reg.predict(x) 13 sse = np.sum((y - y_hat) **2, axis=0) 14 sse = sse / (n - p - 1) 15 s = np.linalg.inv(np.dot(x.T, x)) 16 std_err = np.sqrt(np.diagonal(sse * s)).round(4) 17 18 t_values = (coef/ std_err).round(4)

csvデータ(total_scoreが目的変数です)

1total_score ob penalty fw par_on putt bunker 283     1 1 57 55 34 1 385 1 3 85 55 38 0 481 0 0 64 50 36 0 590 1 1 53 27 37 1 686 1 1 42 27 34 1 786 0 0 57 33 31 0 885 2 2 78 55 36 1 986 3 0 50 22 31 0 1087 0 0 71 27 32 1 1186 0 2 42 22 33 0 1282 0 2 57 66 37 1 1393 2 1 28 11 33 0 1488 1 0 50 16 31 0 1590 2 0 46 27 33 1 1681 0 1 50 27 31 0 1780 0 0 57 38 29 0 1885 1 0 85 33 31 0 1985 0 1 71 22 33 0 2089 0 0 57 33 37 0 2183 1 0 64 50 32 0
#スプレッドシートでの計算結果 ob 2.0533 penalty -0.822 fw 0.1249 par_on -4.1637 putt 3.1677 bunker 0.7899
#現在作っているアプリ上での計算結果 ob 2.1573 - penalty -0.9684 fw 0.1144 par_on -4.7625 putt 12.6963 bunker 0.8931
#Djangoを使用しない、google colab上での計算結果 ob 2.1573 - penalty -0.9684 fw 0.1144 par_on -4.7625 putt 12.6963 bunker 0.8931 (アプリ上と完全に同じになりました)

google colabではcsvファイルを読み込む方法と、csvと同じデータを手書きでリストを作る方法の両方を試しましたが、どちらも同じ値になりました。

puttの値が大きくなり過ぎてしまいます。他の項目("total_score", "ob", "penalty", "fw")は全て正しく計算できています。
計算部分のみ載せています。

試したこと

puttの値だけ上手く変数に入れられていないのではと思い、xをテンプレートに渡し値を確認しましたが問題ありませんでした。
同じくcoefとstd_errの値を確認しましたが、どちらともおかしい値でした(エクセルなどで確認した値と比較して)。

補足情報(FW/ツールのバージョンなど)

django3
python3
ここにより詳細な情報を記載してください。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/03/23 06:49

何がどうと言う前に問題点をちゃんと「自分で」切り分けましょう。
can110

2023/03/23 07:58

django処理はおいといて - dfデータ内容とPython上でのT値 - Excelで同データを検証したときの(できれば手順と)T値などの結果。 といった具体的なものを提示すると回答得られやすくなるかと思います。 とくにdfデータが数十行程度であればCSV形式のテキストとして質問に追記なりすると 第三者が実行、検証しやすくなります。
meg_

2023/03/23 11:16

・django上でDBから値を取得する処理に問題はありませんか? ・djangoを介さずにDBとPythonで重回帰分析で実行した場合は正しい結果が得られますか?
yoshiringoo

2023/03/24 03:52

dameo様 ありがとうございます。 can110様 ご返信ありがとうございます。質問するにあたり情報不足で大変失礼いたしました!csvデータを追記しましたので、もしお時間ございましたら確認頂ければ大変助かります。よろしくお願いします。 meg_様 ご返信ありがとうございます。 views.pyのxの値をテンプレートに渡して確認してみたのですが、csvファイル通りの値がしっかり入っていました。 シンプルにpythonでまず試してみるという基本的なことを失念しておりました・・・ありがとうございます。本文に追記させていただきましたが、それでも間違った値になってしまいました。
guest

回答1

0

ベストアンサー

回帰分析については詳しくありませんが、t値の求め方元のデータが標準化されていないことが原因だと思われます。
提示コードでは以下などを参考に係数(coef)のみから求めていると思います。

上記の場合、事前にデータを標準化することで切片項がなくなって正しい結果が得られるようです。
参考:【重回帰分析】標準化と切片の扱いについて (表現の違いについて)

いっぽう以下では切片(intercept)も含めて求めるようなコードになっています。

この方法であれば元のデータのままでもstatsmodels.regression.linear_model.OLSでの結果と一致します。

Python

1import numpy as np 2import pandas as pd 3from io import StringIO 4from sklearn.linear_model import LinearRegression 5import statsmodels.api as sm 6 7# データ 8s = """total_score,ob,penalty,fw,par_on,putt,bunker 983,1,1,57,55,34,1 1085,1,3,85,55,38,0 1181,0,0,64,50,36,0 1290,1,1,53,27,37,1 1386,1,1,42,27,34,1 1486,0,0,57,33,31,0 1585,2,2,78,55,36,1 1686,3,0,50,22,31,0 1787,0,0,71,27,32,1 1886,0,2,42,22,33,0 1982,0,2,57,66,37,1 2093,2,1,28,11,33,0 2188,1,0,50,16,31,0 2290,2,0,46,27,33,1 2381,0,1,50,27,31,0 2480,0,0,57,38,29,0 2585,1,0,85,33,31,0 2685,0,1,71,22,33,0 2789,0,0,57,33,37,0 2883,1,0,64,50,32,0""" 29df = pd.read_csv(StringIO(s)) 30x = df.drop(['total_score'], axis=1) 31y = df['total_score'] 32 33 34#------------------------------------------------------------------------------- 35# 質問のコード 36 37reg = LinearRegression() 38results = reg.fit(x,y) 39coef = reg.coef_.round(4) 40n = x.shape[0] 41p = x.shape[1] 42 43y_hat = reg.predict(x) 44sse = np.sum((y - y_hat) **2, axis=0) 45sse = sse / (n - p - 1) 46s = np.linalg.inv(np.dot(x.T, x)) 47std_err = np.sqrt(np.diagonal(sse * s)).round(4) 48 49t_values = (coef/ std_err).round(4) 50print(t_values) 51# [ 2.1573 -0.9684 0.1144 -4.7625 12.6963 0.8931] 52 53 54# 以下とコードを合わせるために 55X = x 56params = np.append(reg.intercept_,reg.coef_) 57predictions = y_hat 58 59 60#------------------------------------------------------------------------------- 61# Find p-value (significance) in scikit-learn LinearRegression 62# https://stackoverflow.com/a/42677750 63 64newX = pd.DataFrame({"Constant":np.ones(len(X))}).join(pd.DataFrame(X)) 65MSE = (sum((y-predictions)**2))/(len(newX)-len(newX.columns)) 66 67# Note if you don't want to use a DataFrame replace the two lines above with 68# newX = np.append(np.ones((len(X),1)), X, axis=1) 69# MSE = (sum((y-predictions)**2))/(len(newX)-len(newX[0])) 70 71var_b = MSE*(np.linalg.inv(np.dot(newX.T,newX)).diagonal()) 72sd_b = np.sqrt(var_b) 73ts_b = params/ sd_b 74print(ts_b) 75# [ 8.48895225 2.14428475 -0.85496786 0.11136259 -4.60776964 3.33811352 0.87347851] 76 77 78#------------------------------------------------------------------------------- 79 80X2 = sm.add_constant(X) 81est = sm.OLS(y, X2) 82est2 = est.fit() 83print(est2.summary()) 84""" 85 coef std err t P>|t| [0.025 0.975] 86------------------------------------------------------------------------------ 87const 64.4012 7.586 8.489 0.000 48.012 80.791 88ob 1.1246 0.524 2.144 0.051 -0.008 2.258 89penalty -0.5263 0.616 -0.855 0.408 -1.856 0.804 90fw 0.0042 0.037 0.111 0.913 -0.077 0.085 91par_on -0.1905 0.041 -4.608 0.000 -0.280 -0.101 92putt 0.7986 0.239 3.338 0.005 0.282 1.315 93bunker 0.9099 1.042 0.873 0.398 -1.340 3.160 94"""

投稿2023/03/24 05:41

編集2023/03/24 08:11
can110

総合スコア38341

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

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

yoshiringoo

2023/03/24 05:59

can110様 こんなご丁寧にありがとうございます!こちらの方法で正しいt値を求めることができました。 また本日回帰分析について調べていたところ、私はデータの標準化を飛ばしていてしまったようでした。標準化をしましたら、正しい値になりましたので下記に載せておきます。 df.apply(lambda x: (x-x.mean())/x.std(), axis=0) とすることで、dfを行毎に標準化できました。 ありがとうございました。
can110

2023/03/24 06:08

なるほど。切片がなくなるので正しい結果が得られるようですね。 勉強になります。回答にも追記しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問