javascriptで歪度と尖度を求めるコード

このQ&Aのポイント
  • javascriptで配列から歪度と尖度を求めるコードの方法について教えてください。
  • 現在は不偏分散を利用して歪度と尖度を求めていますが、よりすっきりしたコードにしたいです。
  • javascriptの計算方法が複雑なため、コピペで使用することが多いです。
回答を見る
  • ベストアンサー

javascriptで歪度と尖度を求めるコード

サイトを参考に不偏分散から歪度と尖度を下記のコードで求めることが出来たのですが、 <!DOCTYPE html> <html lang="ja"> <head> <meta charset=utf-8 > <title>unbiased_Variance</title> </head> <body> <script> const arr = [70,71,70,74,75,73,72] // 平均値を計算 let sum = 0; arr.forEach((x, i) => sum += x) const ave = sum / arr.length; // 分散を計算 let dist = 0; arr.forEach((x, i) => dist += (x - ave) ** 2) const unbiasedVariance = dist / (arr.length-1); //不偏分散 const SD = Math.sqrt(dist / (arr.length-1)); // 歪度と尖度を計算 let sum3 = 0; let sum4 = 0; for (var i in arr){ sum3 += Math.pow((arr[i] - ave)/SD, 3); sum4 += Math.pow((arr[i] - ave)/SD, 4); } const skew = sum3*arr.length/(arr.length-1)/(arr.length-2); const exKurt = arr.length*(arr.length+1)/(arr.length-1)/(arr.length-2)/(arr.length-3)*sum4 - 3*(arr.length-1)*(arr.length-1)/(arr.length-2)/(arr.length-3); console.log(unbiasedVariance); console.log(skew); console.log(exKurt); </script> </body> </html> javascriptはコピペで使用が主なので複雑な計算方法の書き方は分かりません、そこでこんな形のコピペのコードが出来上がりました。 配列から歪度と尖度を求めるコードをもっとすっきりした形になればと思い質問しました。もし宜しければご教授お願います。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

const arr = [70,71,70,74,75,73,72]; { const add = (a, b) => a + b, sub = (a, b) => a - b, sum = a=> a.reduce (add, 0), average = a=> sum (a) / a.length, devsq = (a, b = average (a))=> sum (a.map (c=> sub (c, b) ** 2)), vara = a=> devsq (a) / (a.length - 1), stdev = a=> vara (a) ** .5, skewness = (a, b = average (a), c = stdev (a), d = a.length)=> sum (a.map (e=> (sub (e, b) / c) ** 3)) * d / ((d-1)*(d-2)), kurtosis = (a, b = average (a), c = stdev (a) ** 4, d = a.length, e = d*(d+1)/((d-1)*(d-2)*(d-3)), f=3*((d-1)**2)/((d-2)*(d-3)))=> sum (a.map (g=> sub (g, b) ** 4 / c - f)) * e; console.log("不偏分散", vara(arr)); console.log("歪度", skewness(arr)); console.log("尖度", kurtosis(arr)); } 回答がないようですね。 あっているか不明。 尖度においてSD値が4乗になっていない

turu575
質問者

お礼

間違えた私の方が標本分散を示すようにしていた. 大変失礼しました。 再度の解答有り難うございます。

turu575
質問者

補足

ありがとうございます。 尖度についてですが >尖度においてSD値が4乗になっていない とありますが、ExcelのKURT関数や参考にしたサイト(https://lookbackmargin.blog/2019/11/13/stats-in-js/)の方法で求めた結果 -1.446375 に対し 尖度 -13.686374999999998 となりました。もう一度確認してみます。 今回、この質問した後私の例を使いWebView2で動作させたところ動かない事が分かり書き換えて動くまでするのにかなり時間が掛かりました(但しそのコードが正しいかも分かりませんが・・)。 またも実感したのがたとえブラウザで動いてもjsのコード書き方をきちんと理解していないコピペではすぐ限界に行き着くことでした。・・・今までこれの繰り返しでしたが 取りあえずお礼まで

その他の回答 (1)

回答No.2

#1 です。 式の展開を勘違いしてた。 4乗の件も勘違い。 すまぬ! const add = (a, b) => a + b, sub = (a, b) => a - b, sum = a=> a.reduce (add, 0), average = a=> sum (a) / a.length, devsq = (a, b = average (a))=> sum (a.map (c=> sub (c, b) ** 2)), vara = a=> devsq (a) / (a.length - 1), stdev = a=> vara (a) ** .5, skewness = (a, b = average (a), c = stdev (a), d = a.length)=> sum (a.map (e=> (sub (e, b) / c) ** 3)) * d / ((d-1)*(d-2)), kurtosis = (a, b = average (a), c = stdev (a) ** 4, d = a.length)=> sum (a.map (g=> (sub (g, b) ** 4) / c)) * d*(d+1)/((d-1)*(d-2)*(d-3)) -3*((d-1)**2)/((d-2)*(d-3)); console.log("不偏分散", vara(arr)); console.log("歪度", skewness(arr)); console.log("尖度", kurtosis(arr));

turu575
質問者

補足

ありがとうございます。計算結果 不偏分散 3.8095238095238098 歪度 0.2881954902926226 尖度 -1.4463749999999966 となり 私の計算とは違い 3.2653061224489797,0.2881954902926226,-1.4463749999999962 不偏分散ではなく標本分散が示されています。

関連するQ&A

  • JavaScriptの問題に関して教えてください。

    下記問題の解き方および答えが考えても全然分からず、お教えいただきたいです。お願いいたします。 以下のプログラムを読んで、どういったプログラムなのかを説明してください。 let change = 0; let change_sum = 0; const data = [ 31, 41, 59, 26, 53, 58, 97, 93, 23, 84 ]; console.log("並べ替える前"); for (let i = 0; i < data.length; i++) { console.log(data[i] + " "); }// for console.log("\n"); console.log("***********************************"); console.log(""); for (let i = 0; i < data.length - 1; i++) { for (let j = i + 1; j < data.length; j++) { if (data[i] > data[j]) { let a = data[i]; data[i] = data[j]; data[j] = a; change++; }// if }// for(内側1) console.log((i + 1) + "回目"); console.log(`${change}回`); for (let k = 0; k < data.length; k++) { process.stdout.write(data[k] + " "); }// for(内側2) console.log("\n"); change_sum += change; change = 0; }// for(外側) //最終結果の表示 console.log("***********************************"); console.log(""); console.log(`${change_sum}回`); console.log("最終結果"); for (let i = 0; i < data.length; i++) { process.stdout.write(data[i] + " "); }// for console.log("");

  • javaでのプログラミング

    javaで平均と分散を求めるプログラムを作っているのですが、 分散の出力がうまくいきません。(出力が0になってしまいます) プログラミングとしておかしいところがあれば、教えていただけませんでしょうか 以下プログラムソースです。 public class test{ public static void main(String[] args){ int i,rand; double ave=0 double bun=0 double sum1=0 double sum2=0; int [] data = new int[10]; rand=(int)(Math.random()*100+0.5); for(i=0;i<10;i++){ data[i]=rand; } for(i=0;i<10;i++){ sum1+=data[i]; sum2+=data[i]*data[i]; } ave=sum1/10; bun=(sum2/10) - (ave*ave); System.out.println(ave); System.out.println(bun); } }

    • ベストアンサー
    • Java
  • c言語

    n人の名前、と国数英の点数を読み込み各人の平均点、標準偏差を求め見やすく出力するぷろぐらむです osはlinuxでコンパイラはgccです。 変数が多くなってしまいよくわかりません。 もっと簡単になりますか? #include<stdio.h> #include<math.h> #define N 50 main() { int eng[N], jap[N], math[N], n=0, i=0; char name[N][12]; double sum[N], SUM, sum1, sum2, sum3, ave1, ave2, ave3, vari, s_devi; printf("名前 合計点"); while(scanf("%s %d %d %d",&name[n],&eng[n],&jap[n],&math[n]) != EOF) { sum[i] = eng[n]+jap[n]+math[n]; sum1 += eng[n]; sum2 += jap[n]; sum3 += math[n]; printf("%-12s%4d",name[n], sum[i]); n++; i++; } ave1 = sum1/n; ave2 = sum2/n; ave3 = sum3/n; for(i=0; i<n; i++) { SUM += (eng[i]-ave1)*(eng[i]-ave1); } vari = SUM/n; s_devi = sqrt(vari); printf("English\n average = %f\nstandard deviation = %f\n\n",ave1,s_devi); for(i=0; i<n; i++) { SUM += (jap[i]-ave2)*(jap[i]-ave2); } vari = SUM/n; s_devi = sqrt(vari); printf("japanese\n average = %f\nstandard deviation = %f\n\n",ave2,s_devi); for(i=0; i<n; i++) { SUM += (math[i]-ave3)*(math[i]-ave3); } vari = SUM/n; s_devi = sqrt(vari); printf("math\n average = %f\n standard deviation = %f\n\n",ave3,s_devi); }

  • 2件一組の文章をランダムに表示する。

    お世話になっております。 早速ですが、A~Dの文章を2件ランダムに表示させたいです。 更新の度に表示される文章を変えたいのです。 ランダムに文字を並べ替えるコトは出来たのですが、 ソコから2件だけ抜き出すのができません。 <script language="javascript"> arr = ["ほげほげA","ほげほげB","ほげほげC","ほげほげD"]; function a(){ for(i=0; i<arr.length; i++){ k = i; k = Math.floor(Math.random()*arr.length); tmp = arr[i]; arr[i] = arr[k]; arr[k] = tmp; } } function b(){ a(); for(j=0; j<arr.length; j++){ document.write(arr[j]); } } b(); </script> ■1回目 ほげほげC ほげほげA ■2回目 ほげほげA ほげほげD のような感じです。 ご助力お願いいたします!

  • 尖度のσ^4の計算

    尖度のσ^4の計算過程を教えてください。 統計学入門(基礎統計学Ⅰ)第6章演習問題前半 6.5<密度関数の規格化定数> https://parco1021.hatenablog.com/entry/2020/04/28/194257 の画像の一番最後の式 (尖度) = (3/35) × (5/1) - 3 = -6/7 が理解できていません。 おそらく、 尖度 = α4 - 3 = {E[(X-μ)^4]}/(σ^4) - 3 = {E[(X-μ)^4]}*{1/(σ^4)} - 3 の式で、 E[(X-μ)^4] = 3/35 にしたものだと思います。 しかし、分からないのは(5/1)です。 その前の計算で、分散V(X)は1/5で出ているので、 これを逆数にしたものだと思いますが、 分散ってσ^2ですよね? 尖度の計算の分母に要求されているのはσ^4なので σ^4 = (σ^2)^2 = (1/5)^2 = 1/25 じゃないんですか? でも、本の答えも-6/7なので、計算自体は1/5で合ってるようです。 ただ、この本は何度も誤植の前科があるのでもう信じられません…。 もし、1/25ではなく、1/5が正しいなら、その説明をお願いします。

  • javascriptで浮動小数点の問題

    javascriptで浮動小数点の問題を解決しつつevalをつかった電卓を作ることはできませんか? >>> //-が欲しい場合 var array2 = str.match(/-?[0-9]+\.?[0-9]*/g); for(var i = 0; i < array2.length; i++) { console.log(parseFloat(array2[i])); } な感じで数値を抜き出し 計算記号+-*/に従ってmathのメソッドを順次呼び出す関数を作成すればいいのです。 計算記号については抜き出した数値を文字列として数えれば抜き出せるはず。 このように教えてもらいましたが、正直難しすぎてさっぱりわかりません。 evalでは浮動小数点の問題は解決できないのでしょうか? 便利なライブラリなどもないでしょうか?

  • javaScriptでカレンダーを作成したい

    カレンダーをjavaScriptで作成しております。 tableをflexして2段のカレンダーです。 ①次へや前へのボタンを押すと前のが削除されず下へ増えていってしまいます。 ②矢印を2回押したら次の次の月を表示したいのができません。 ご教授お願いいたします。 Java Script let topicsData = [ ["1", "1日です"], ["4", "4日です"], ["9", "9日です"], ["15", "15日です"], ["27", "27日です"] ] function showProcess(year, month) { const lastday = new Date(year, month + 1, 0).getDate() + 1; const topics = new Array(); for (i = 0; i <= lastday; i++) { topics[i] = ""; } for (i = 0; i < topicsData.length; i++) { topics[topicsData[i][0]] = topicsData[i][1]; } //HTMLタグをつくる const table = document.getElementById("calendarleft"); for (let i = 1; i <= 15; i++) { let tr = document.createElement("tr"); //tdタグ(日付)    let td = document.createElement("td"); td.textContent = i; //tdタグ(曜日)   day = new Date(year, month, i); days = day.getDay(); weekjp = new Array("日", "月", "火", "水", "木", "金", "土"); weeks = weekjp[days]; let tdWeek = document.createElement("td"); tdWeek.innerText = weeks; //tdタグ(トピックス)  let topicsText = document.createElement("td"); topicsText.innerText = topics[i]; console.log(topics[i]); //HTMLに表示させる document.querySelector('#header').innerHTML = (month + 1) + "月"; table.appendChild(tr); tr.appendChild(td); tr.appendChild(tdWeek); tr.appendChild(topicsText); } const table2 = document.getElementById("calendarright"); for (let i = 16; i < lastday; i++) { let tr = document.createElement("tr"); //tdタグ(日付)    let td = document.createElement("td"); td.textContent = i; //tdタグ(曜日)   day = new Date(year, month, i); days = day.getDay(); weekjp = new Array("日", "月", "火", "水", "木", "金", "土"); weeks = weekjp[days]; let tdWeek = document.createElement("td"); tdWeek.innerText = weeks; //tdタグ(トピックス)  let topicsText = document.createElement("td"); topicsText.innerText = topics[i]; console.log(topics[i]); //HTMLに表示させる document.querySelector('#header').innerHTML = (month + 1) + "月"; table2.appendChild(tr); tr.appendChild(td); tr.appendChild(tdWeek); tr.appendChild(topicsText); } } const today = new Date(); let showDate = new Date(today.getFullYear(),today.getMonth(),1); window.onload = function () { showProcess(today.getFullYear(),today.getMonth()); }; function prev() { showProcess(showDate.getFullYear(),showDate.getMonth()-1); } function next() { showProcess(showDate.getFullYear(),showDate.getMonth()+1); }

  • 100x100行列の平均値を求めたい

    const int SIZE=100; for(int i=0; i< SIZE; i++){ for(int j=0; j< SIZE; j++){ fin >> array[i][j]; } } double sum=0.0; double ave=0.0; int J =3; for(int i=0; i< SIZE; i++){ sum += array[i][J]; } ave = sum / SIZE; cout << sum << endl; cout << ave << endl; 100x100行のファイルを読み込んで、すべての行の足し算および平均値を求めたいと思います。上のようある列(または行)を固定して求めることは出来るのですが、一度に0~99までの足し算および平均値を求めるやり方はどのようにしたらよろしいのでしょうか?たぶんfor文を使えば、できるのかなとは思うのですが、なかなか思うように行きません。 アドバイスよろしくお願いいたします。

  • 最大値と最小値の求め方

    以下はコマンドライン引数で任意の数の整数を受け取って、合計・平均・最大・最小を求めようとしたソースです。 しかし、実行したら最大値と最小値が正しく出ませんでした。 if文が間違っているのかもしれないと思ったのですが、はっきりと『ここが間違っている』という場所が分かりません。 どうかご指摘お願いします。 class Choco { public static void main (String[] args) { int i; int sum = 0; int max; int min; for ( i=0; i<args.length; i++) sum += Integer.parseInt(args[i]); double ave = sum/args.length; max = args.length; min = args.length; if (args.length>max){ max = args.length; } if (args.length<min){ min = args.length; } System.out.println("合計は" + sum + "です。"); System.out.println("平均は" + ave + "です。"); System.out.println("最大値は" + max + "です。"); System.out.println("最小値は" + min + "です。"); } }

    • ベストアンサー
    • Java
  • バブルソートの組み込み方について

    情報の授業で10人分の点数を打ち込み、その平均点と標準偏差を出し、点数の高い順に並べるプログラムをC言語で作れという課題が出されました。 以下のソースのように平均点と標準偏差を出すところまではいったんですが、バブルソートをどう組み込めばいいのかわかりません。 どなたか教えてくれませんか? #include <stdio.h> #include <math.h> main() { float data[ 10 ], sum = 0, ave, s; int i, n = 10; for( i = 0; i < n; i++ ) { printf( "%d人目の点数 = ", i+1); scanf( "%f", &data[ i ] ); sum += data[ i ]; } ave = sum / n; for( i = 0; i < n; i++ ) { s += ( data[ i ] - ave ) * ( data[ i ] - ave ); } s = sqrt( s / ( n - 1 ) ); printf( "平均値・・ %f\n", ave ); printf( "標準偏差・・ %f\n", s ); return 0; }

専門家に質問してみよう