fc2ブログ

PyQtを使う

 RにGUIがないので、R.NET(C#)でGUIを作成してみたのが前回のお話でした。最近よく使うPythonでも似たような内容に直面しています。ただ、Pythonの方はRに比べ、いろいろとGUIの作り方(アプローチ)があるようですね。今回は、PyQtを使って簡単なGUIを作ってみました。
 PyQtはフリーウェアでセットアップは「pip install pyqt5」でOK。GUIの作成ツールは、Anacondaをインストールした際に、一緒にセットアップされている「Qt Designer」を使います。designer.exeは、私の環境では以下のフォルダ内に入っていたので実行します。
C:\Anaconda3\Library\bin
 起動画面は以下の通りです。➀Main Window、➁画面サイズの順に選択し、➂作成ボタンを押します。Qt_designer1_180225.png Visual Studioのような画面が表示されますので、同じ要領でFormを作成します。Qt_designer2_180225.png 各オブジェクトのプロパティもVSと同じような操作です。オブジェクトを配置した後には「シグナル/スロットエディタ」で動作を設定します。この部分はVSと違った感があり、いまいち理解できていません・・。とりあえず、ボタンをクリックしたときにイベントが上がるような暫定設定をしました。作成時に「Ctrl + R」を押すと、プレビュー画面を確認できます。Qt_designer3_180225.png Formとシグナル/スロットエディタによる動作を含め、保存すると、uiファイルが作成されます。中身はxmlファイルです。
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
・・・・
 次に、uiファイルをpyファイルに変換します。作成したTestWindow.uiからTestWindow.pyを作成する場合は以下のコマンドをコマンドプロンプトから実行します。
python -m PyQt5.uic.pyuic -x TestWindow.ui -o TestWindow.py
ui_to_py変換_180225 変換されたTestWindow.pyをVisual Studio Code上で実行してみると、いい感じに表示できました。VScode確認_180225 そのまま、VSCodeでイベント/アクション関連を手直ししました。ソフトの仕様は、以下の通りです。
  ➀  スピンボタンを動かすと、LCDにその値が表示される。
  ➁  Input1ボタンを押すと、Outputに既定の文字が表示され、LCDにボタンの番号(1)が表示される。
  ➂  Input2ボタンを押すと、Inputボックス内の文字列がOutputボックスに表示され、LCDにボタンの番号(2)が表示される。
  ④ Clearボタンを押すと、Inputボックス、Outputボックスの文字がクリアされ、スピンボタンとLCDが初期値(0)に戻る。
 完成版のプログラムは以下の通りです。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'TestWindow.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.Japanese, QtCore.QLocale.Japan))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.Input1_btn = QtWidgets.QPushButton(self.centralwidget)
self.Input1_btn.setGeometry(QtCore.QRect(440, 140, 112, 34))
self.Input1_btn.setObjectName("Input1_btn")
self.Input2_btn = QtWidgets.QPushButton(self.centralwidget)
self.Input2_btn.setGeometry(QtCore.QRect(440, 200, 112, 34))
self.Input2_btn.setObjectName("Input2_btn")
self.Clear_btn = QtWidgets.QPushButton(self.centralwidget)
self.Clear_btn.setGeometry(QtCore.QRect(440, 320, 112, 34))
self.Clear_btn.setObjectName("Clear_btn")
self.InputTextBox = QtWidgets.QTextEdit(self.centralwidget)
self.InputTextBox.setGeometry(QtCore.QRect(70, 90, 291, 101))
self.InputTextBox.setObjectName("InputTextBox")
self.InputLabel = QtWidgets.QLabel(self.centralwidget)
self.InputLabel.setGeometry(QtCore.QRect(30, 60, 75, 18))
self.InputLabel.setObjectName("InputLabel")
self.lcdNumber = QtWidgets.QLCDNumber(self.centralwidget)
self.lcdNumber.setGeometry(QtCore.QRect(516, 40, 41, 51))
font = QtGui.QFont()
font.setPointSize(20)
self.lcdNumber.setFont(font)
self.lcdNumber.setLayoutDirection(QtCore.Qt.RightToLeft)
self.lcdNumber.setAutoFillBackground(False)
self.lcdNumber.setStyleSheet("QLCDNumber{\n"
" color: rgb(255, 255, 0);\n"
" background-color: rgb(128, 128, 128);\n"
" font: 20pt \"MS UI Gothic\";\n"
"}")
self.lcdNumber.setSmallDecimalPoint(False)
self.lcdNumber.setDigitCount(1)
self.lcdNumber.setSegmentStyle(QtWidgets.QLCDNumber.Flat)
self.lcdNumber.setObjectName("lcdNumber")
self.OutputTextBox = QtWidgets.QTextBrowser(self.centralwidget)
self.OutputTextBox.setGeometry(QtCore.QRect(70, 240, 291, 101))
self.OutputTextBox.setObjectName("OutputTextBox")
self.OutputLabel = QtWidgets.QLabel(self.centralwidget)
self.OutputLabel.setGeometry(QtCore.QRect(30, 210, 75, 18))
self.OutputLabel.setObjectName("OutputLabel")
self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.spinBox.setGeometry(QtCore.QRect(430, 40, 61, 51))
font = QtGui.QFont()
font.setPointSize(20)
self.spinBox.setFont(font)
self.spinBox.setObjectName("spinBox")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 31))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.retranslateUi(MainWindow)
#self.Clear_btn.clicked.connect(self.Clear_btn.click)
#self.Input1_btn.clicked.connect(self.Input1_btn.click)
#self.Input2_btn.clicked.connect(self.Input2_btn.click)
#self.spinBox.valueChanged['int'].connect(self.spinBox.setValue)
self.Input1_btn.clicked.connect(self.func1)
self.Input2_btn.clicked.connect(self.func2)
self.Clear_btn.clicked.connect(self.clear)
self.spinBox.valueChanged['int'].connect(self.lcdout)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.Input1_btn.setText(_translate("MainWindow", "Input 1"))
self.Input2_btn.setText(_translate("MainWindow", "Input 2"))
self.Clear_btn.setText(_translate("MainWindow", "Clear"))
self.InputLabel.setText(_translate("MainWindow", "Input"))
self.OutputLabel.setText(_translate("MainWindow", "Output"))

def lcdout(self):
self.lcdNumber.display(self.spinBox.text())

def func1(self):
self.OutputTextBox.setText("Input 1 Button has clicked!")
self.lcdNumber.display(1)

def func2(self):
self.OutputTextBox.setText(self.InputTextBox.toPlainText())
self.lcdNumber.display(2)

def clear(self):
self.InputTextBox.clear()
self.OutputTextBox.clear()
self.spinBox.setValue(0)
self.lcdNumber.display(0)

if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
70~73行目(修正前)から74~77行目(修正後)に手直ししました。また、89~104行目にアクション用の関数を追加しました。

➀の実行結果です。PyQt実行結果Win1_180225➁の実行結果です。PyQt実行結果Win2_180225➂の実行結果です。PyQt実行結果Win3_180225すべて、問題なく仕様通り動作しました。

 Python(PyQt)の良い所は、プラットフォームを選ばない所でしょう。同じ上記プログラム(TestWindow.py)をMacBook Airにコピーし、VS Code上で実行しました。PyQt実行結果Mac1_180225PyQt実行結果Mac2_180225PyQt実行結果Mac3_180225 これも問題なしです。同じプログラムでプラットフォームを選ばない魅力、大変素晴らしいですね。.NET Frameworkがはるかに霞んで見えます・・。
スポンサーサイト



R.NETを使う(2)

 昨年末R.NETを触って以来のかなりのご無沙汰です。その後も、個人利用ではなく、多くのRをインストールしていないユーザにRを使ってもらうには、システムをどのように実装したらよいのか紆余曲折しています・・。
 さすがにGUIのないシステムは分かりづらく、使ってもらえませんからね。加えて、システム管理する側としてもメンテしやすくなければなりません。

 前回の基本統計量(記述統計量)を例に、R.NET(C#)でコーディングしてみました(C#は大変久々。最近はR、Pythonで遊ぶことが多い・・)。。完成したソフトウェアの画面はこんな感じです。RNET_180225.png 「Data Readボタン」を押すと、exeファイルのあるフォルダ内のData.csvを読み込み、datagridview(Data領域)に表示します。次に「Calc1ボタン」を押すと、Rで解析を実施し、ヒストグラムと基本統計量結果を表示します。
 プログラムは、Form部(MainForm.cs)と解析クラス部(BasicStat.cs)に分けて作成しました。Form部のプログラムは以下の通りです。ヒストグラムの結果画像は特定フォルダ内に保存しておき、その画像ファイルを読み込む(原始的な?)スタイルです。
//MainForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;

namespace R_tools_CS
{
public partial class MainForm : Form
{
List<string> datastr = new List<string>();
BasicStat bs = new BasicStat();

public MainForm()
{
InitializeComponent();
}

private void Calc1_Click(object sender, EventArgs e)
{
bs.func1(datastr); //call R-function

//results output
ResultsBox.Clear();
ResultsBox.AppendText("Summary function" + " \r\n");
ResultsBox.AppendText(" Min. : " + bs.summary_cs[0] + " \r\n");
ResultsBox.AppendText(" 1st Qu. : " + bs.summary_cs[1] + " \r\n");
ResultsBox.AppendText(" Median : " + bs.summary_cs[2] + " \r\n");
ResultsBox.AppendText(" Mean : " + bs.summary_cs[3] + " \r\n");
ResultsBox.AppendText(" 3rd Qu. : " + bs.summary_cs[4] + " \r\n");
ResultsBox.AppendText(" Max. : " + bs.summary_cs[5] + " \r\n");
ResultsBox.AppendText(" \r\n");

ResultsBox.AppendText("Average : " + String.Format("{0:0.000}", bs.avg_cs) + " \r\n");
ResultsBox.AppendText("Standard error : " + String.Format("{0:0.000}",bs.std_cs/Math.Sqrt(bs.n_cs)) + " \r\n");
ResultsBox.AppendText("Median : " + String.Format("{0:0.000}", bs.median_cs) + " \r\n");
ResultsBox.AppendText("Standard deviation : " + String.Format("{0:0.000}",bs.std_cs) + " \r\n");
ResultsBox.AppendText("Variance : " + String.Format("{0:0.000}", bs.var_cs) + " \r\n");
ResultsBox.AppendText("Range : " + String.Format("{0:0.000}", bs.max_cs-bs.min_cs) + " \r\n");
ResultsBox.AppendText("Minimum : " + String.Format("{0:0.000}", bs.min_cs) + " \r\n");
ResultsBox.AppendText("Maximum : " + String.Format("{0:0.000}", bs.max_cs) + " \r\n");
ResultsBox.AppendText("Summation : " + String.Format("{0:0.000}", bs.sum_cs) + " \r\n");
ResultsBox.AppendText("Data number : " + String.Format("{0:0.000}", bs.n_cs) + " \r\n");

DrawPicture(); //draw picture
}

//draw picture
private void DrawPicture()
{
//display image
using (System.IO.StreamReader str = new System.IO.StreamReader(bs.imgPath))
{
this.pictureBox1.Image = new Bitmap(str.BaseStream);
str.Close();
}
this.pictureBox1.Invalidate();
}

//Data Read
private void DataRead_btn_Click(object sender, EventArgs e)
{
string line = "";
StreamReader sr = new StreamReader("data.csv", Encoding.GetEncoding("Shift_JIS"));

while ((line = sr.ReadLine()) != null)
{
datastr.Add(line);
}
sr.Close();

//display data
dataGridView1.Rows.Clear();
dataGridView1.Columns.Clear();
dataGridView1.ColumnCount = 2;
DataGridViewColumn column0= dataGridView1.Columns[0];
column0.Width = 30;
DataGridViewColumn column1 = dataGridView1.Columns[1];
column1.Width = 40;
for (int i = 0; i < datastr.Count; i++)
{
dataGridView1.Rows.Add(i+1, datastr[i]);
}
}
}
}
 次に、解析クラス部のプログラムです。Rのコマンドは、R.NETのREngineのインスタンス(今回はre)を使って、「re.Evaluate」で呼び出し続けるシンプルなものです。注意点は、Rの変数(○○_rと表記)からC#の変数(○○_csと表記)に結果を代入する際に、ほとんどの場合、「○○_r[0]」のように先頭データを取得する与えること。47~51行目のsummary関数は、Min.、1st Qu.、Median、Mean、3rd Qu.、Max.の6つの値が[0]~[5]に代入されていました。関数により、いくつの値が返ってくるか、目的の値が何番目に入っているか確認が必要です。今回は、デバックモードでブレークポイントを作って、変数を確認することですぐ分かりました。
//BasicStat.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RDotNet;

namespace R_tools_CS
{
class BasicStat
{
private REngine re;
public string imgPath = @"c:\\temp\\RDotnet.png"; //temporary result image path

//analysis data
public double[] summary_cs = new double[6];
public int n_cs;
public double avg_cs;
public double median_cs;
public double std_cs;
public double var_cs;
public double max_cs;
public double min_cs;
public double sum_cs;

//calculate basic statistic values
public void func1(List<string> dataliststr) {

REngine.SetEnvironmentVariables();
re = REngine.GetInstance();

//data array create
string datastr = "";
for (int i = 0; i < dataliststr.Count; i++)
{
if (i > 0) { datastr += ","; }
datastr += dataliststr[i];
}

//R command run

//data x
string sendcommand = "x <- c(" + datastr + ")";
var x = re.Evaluate(sendcommand).AsNumeric();

//summary statistics
var summary_r = re.Evaluate("summary(x)").AsNumeric();
for (int i= 0; i < 6; i++)
{
summary_cs[i] = double.Parse(summary_r[i].ToString());
}

//data number
var n_r = re.Evaluate("length(x)").AsNumeric();
n_cs = int.Parse(n_r[0].ToString());

//mean
var avg_r = re.Evaluate("mean(x)").AsNumeric();
avg_cs = double.Parse(avg_r[0].ToString());

//median
var median_r = re.Evaluate("median(x)").AsNumeric();
median_cs = double.Parse(median_r[0].ToString());

//standard deviation
var std_r = re.Evaluate("sd(x)").AsNumeric();
std_cs = double.Parse(std_r[0].ToString());

//variance
var var_r = re.Evaluate("var(x)").AsNumeric();
var_cs = double.Parse(var_r[0].ToString());

//maximum
var max_r = re.Evaluate("max(x)").AsNumeric();
max_cs = double.Parse(max_r[0].ToString());

//minimum
var min_r = re.Evaluate("min(x)").AsNumeric();
min_cs = double.Parse(min_r[0].ToString());

//summation
var sum_r = re.Evaluate("sum(x)").AsNumeric();
sum_cs = double.Parse(sum_r[0].ToString());

//histgram
int picWidth = 320;
int picHeight = 240;
re.Evaluate(String.Format(@"png('{0}', width={1}, height={2}, bg='transparent');", imgPath, picWidth, picHeight));
re.Evaluate("hist(x, col = 'orange', border = '#ff00ff', main = 'Histgram', breaks= 'Scott')");
re.Evaluate("graphics.off();");
}
}
}
問題なくソフトウェアは動作しました。結果も当然ですが、同じです。今回は前回結果出力していた、Mode、Kurtosis、Skewnessの計算はしていません。RのForループを使った計算をしたものです。まだ勉強が足りないので、後日改めて求めたいと思います。

Excel分析ツールを見直す(7)

 前回の続きです。今回は「基本統計量」をRPythonで求めます。Excelでは「基本統計量」と呼んでいますが、この用語は他に「要約統計量」、「記述統計量」とも呼ばれています。
 まず、前回の関数まとめ表を再度アップします。基本統計量まとめ_1802122.R
 Rのプログラムは以下の通りです。
# summary statistics
# data
x <- c(73,61,68,71,89,64,73,66,60,60,64,71,75,86,59,93,93,58,65,54,52,46,63,59,59,85,52,51,67,87,86,80,44,52,111,59,64,64)

summary(x) # summary statistics

n <- length(x) # data number
avg <- mean(x) # mean
std <- sd(x) # standard deviation

# mode
xt <- table(x)
modeval_tmp <- xt[xt == max(xt)]
modeval <- array(0,dim=c(5))

for(i in 1:length(modeval_tmp)){
modeval[i] <- as.integer(names(which.max(modeval_tmp[i])))
}

# kurtosis
kurtosis <- 0
calctmp <- 0
for(i in 1:n){
calctmp <- calctmp + ((x[i]-avg)/std)^4
}
kurtosis <- n*(n+1)/((n-1)*(n-2)*(n-3))*calctmp - 3*(n-1)^2/((n-2)*(n-3))

#skewness
skewness <- 0
calctmp <- 0
for(i in 1:n){
calctmp <- calctmp + ((x[i]-avg)/std)^3
}
skewness <- n/((n-1)*(n-2))*calctmp

sprintf("Average = %f",avg)
sprintf("Standard Error = %f",std/sqrt(n))
sprintf("Median = %f",median(x))
for(i in 1:length(modeval_tmp)){
show(sprintf("Mode = %d", modeval[i]))
}
sprintf("Standard deviation = %f",std)
sprintf("Variance = %f",var(x))
sprintf("Kurtosis = %f",kurtosis)
sprintf("Skewness = %f",skewness)
sprintf("Range = %f",max(x)-min(x))
sprintf("Minimum = %f",min(x))
sprintf("Maximum = %f",max(x))
sprintf("Summation = %f",sum(x))
sprintf("Data number = %d",n)
 Rにはsummary関数(プログラムの5行目)があり、上表の赤字の項目を一括で求めることができます。大変便利です。
 最頻値(*2)は標準関数が見当たらなかったので、12行目のtable関数を使ってデータ頻度を集計し、頻度の最大値のデータを求める方法を取りました。余談ですが、39~41行目の複数の最頻値を出力する際に、初めはsprintf関数をforループで使用したのですが、値が出力されない不可解な問題に直面しました。結局、show関数と組み合わせて表示できましたが、なぜsprintf関数のみで表示できなかったのかは分からずじまいです・・。
 また、尖度(*3)と歪度(*4)も標準関数を見つけられず、前回の定義(1)、(2)式から計算しました。
 実行結果は、以下の通りです。

summary(x) # summary statistics
Min. 1st Qu. Median Mean 3rd Qu. Max.
44.0 59.0 64.0 68.0 74.5 111.0

Average = 68.000000
Standard Error = 2.402583
Median = 64.000000
Mode = 59
Mode = 64
Standard deviation = 14.810515
Variance = 219.351351
Kurtosis = 0.556624
Skewness = 0.840495
Range = 67.000000
Minimum = 44.000000
Maximum = 111.000000
Summation = 2584.000000
Data number = 38
 Excelの基本統計量と同じ結果が得られました。最頻値も2つ求められ、表示できました。

3.Python
 Pythonのプログラムでは、➀numpyとscipy.statsを使う場合、➁pandasを使う場合の2種類を試しました。➀numpyとscipy.statsを使う場合のプログラムは以下の通りです。
import numpy as np
from scipy import stats

x = np.array([73,61,68,71,89,64,73,66,60,60,64,71,75,86,59,93,93,58,65,54,52,46,63,59,59,85,52,51,67,87,86,80,44,52,111,59,64,64])

n = len(x)
avg_value = np.mean(x)
std_value = np.std(x, ddof = 1)

print("Mean = " + str(avg_value)) # mean
print("Standard error = " + str(std_value / np.sqrt(n))) # standard error
print("Median = " + str(np.median(x))) # median
print("Mode = " + str(stats.mode(x))) # mode
print("Standard Deviation = " + str(std_value)) # standard deviation
print("Variance = " + str(np.var(x, ddof = 1))) # variance

print("Kurtosis(stats lib) = " + str(stats.kurtosis(x))) # kurtosis
kurtosis_value = 0
calctmp = 0.0
for i in range(1, n):
calctmp += ((x[i]-avg_value)/std_value)**4
kurtosis_value = n*(n+1)/((n-1)*(n-2)*(n-3))*calctmp - 3*(n-1)**2/((n-2)*(n-3))
print("Kurtosis(Calc.) = " + str(kurtosis_value)) # kurtosis

print("Skewness(stats lib) = " + str(stats.skew(x))) # skewness
skewness_value = 0
calctmp = 0
for i in range(1, n):
calctmp += ((x[i]-avg_value)/std_value)**3
skewness_value = n/((n-1)*(n-2))*calctmp
print("Skewness(Calc.) = " + str(skewness_value)) # skewness

print("Range = " + str(np.max(x)-np.min(x))) # range
print("Minimum = " + str(np.min(x))) # minimum
print("Maximum = " + str(np.max(x))) # maximum
print("Summation = " + str(np.sum(x))) # summation
print("Data number = " + str(n)) # data number
print("1Q = " + str(stats.scoreatpercentile(x, 25))) #1Q
print("3Q = " + str(stats.scoreatpercentile(x, 75))) #3Q
 13行目の最頻値ですが、scipy.statsのmode関数を使う場合、最頻値が複数あると、一番小さなデータしか求めることができないとのこと(*5)。複数の最頻値がある場合には使えませんね・・。
 また、注意点としては標準偏差、分散を求める際は、「ddof=1」の設定を行う必要があります(*6)。設定しない場合(defaultは0)は、母集団の値になってしまいます。
 結果は以下の通りです。
Mean                = 68.0
Standard error = 2.40258277338
Median = 64.0
Mode = ModeResult(mode=array([59]), count=array([4]))
Standard Deviation = 14.8105148915
Variance = 219.351351351
Kurtosis(stats lib) = 0.3321873494749976
Kurtosis(Calc.) = 0.556211154624
Skewness(stats lib) = 0.8069472243990693
Skewness(Calc.) = 0.839397616767
Range = 67
Minimum = 44
Maximum = 111
Summation = 2584
Data number = 38
1Q = 59.0
3Q = 74.5
 尖度と歪度については、stats lib内に関数があったので、それを使ったのですが、ExcelやRで求めた値と異なる結果でした(7、9行目)。算出する数式が違うのでしょうか?ネットで調べたのですが、情報を掴めずじまいです・・。結局、前回の定義(1)、(2)式から計算しました。ところがその値も微妙に異なります(8、10行目)。計算の過程で数字が丸められているのでしょうか?うーん、すごく気持ち悪いです・・。

 気持ち悪さを持ちつつ、➁pandasを使う場合のプログラムを書きました。
import numpy as np
import pandas as pd

x = np.array([73,61,68,71,89,64,73,66,60,60,64,71,75,86,59,93,93,58,65,54,52,46,63,59,59,85,52,51,67,87,86,80,44,52,111,59,64,64])

dfx = pd.Series(x) # dataframe

print("Mean = " + str(dfx.mean())) # mean
print("Standard error = " + str(dfx.sem())) # standard error
print("Median = " + str(dfx.median())) # median
print("Mode = " + str(dfx.mode())) # mode
print("Standard Deviation = " + str(dfx.std())) # standard deviation
print("Variance = " + str(dfx.var())) # variance
print("Kurtosis = " + str(dfx.kurtosis())) # kurtosis
print("Skewness = " + str(dfx.skew())) # skewness
print("Range = " + str(dfx.max()-dfx.min())) # range
print("Minimum = " + str(dfx.min())) # minimum
print("Maximum = " + str(dfx.max())) # maximum
print("Summation = " + str(dfx.sum())) # summation
print("Data number = " + str(dfx.count())) # data number
print("1Q = " + str(dfx.quantile(0.25))) #1Q
print("3Q = " + str(dfx.quantile(0.75))) #3Q
 算出したい項目について、すべて関数を持っています。さすがです。結果は以下の通りです。
Mean                = 68.0
Standard error = 2.40258277338
Median = 64.0
Mode = 0 59
1 64
dtype: int32
Standard Deviation = 14.810514891500274
Variance = 219.35135135135135
Kurtosis = 0.556624083565
Skewness = 0.840495304759
Range = 67
Minimum = 44
Maximum = 111
Summation = 2584
Data number = 38
1Q = 59.0
3Q = 74.5
 結果もExcelやRと同じでバッチリです。最頻値も59と64の2つのデータを検出できました(4、5行目)。Pythonで「基本統計量(要約統計量)」を求めるときは、pandasが便利で良いと思いました。
 今回も大変勉強になりました。

Excel分析ツールを見直す(6)

 ヒストグラム、回帰分析に続いて、今回は「基本統計量」です。Excelの分析ツールでヒストグラム、回帰分析はよく使うのですが、この「基本統計量」は使ったことがありませんでした。それほど必要性がなかったからかもしれません・・・。

1. Excel
 Excelのメニューから、「データ」-「データ分析」を選択すると、「データ分析ウィンドウ」が立ち上がりますので、「基本統計量」を選択し、OKボタンを押します。基本統計量1_180212 「基本統計量ウィンドウ」が立ち上がりますので、入力範囲と出力先を設定します。この時、「統計情報」にチェックを入れておきます。入力データは38個の1次元データを準備しました。OKボタンを押すと、結果が出力されます。基本統計量2_180212 基本統計量として、平均、標準偏差、分散、最大値、最小値のような一般的な統計量とともに、聞き慣れない「尖度(せんど)」や「歪度(わいど)」などの値も出てきました。基本統計量3_180212 尖度は(1)式で与えられ、全データの分布を描いた時に、どれだけとがっているかを示した値で、正規分布を基準(Ku=0)として、とがっている場合は正(Ku>0)、なだらかな場合は負(Ku<0)の値を取るとのこと。尖度_180212
 歪度は(2)式で与えられ、全データの分布を描いた時に、左右対称を基準にどれくらい歪んでいるかを示す値で、正規分布を基準(Sk=0)として、テールが右(ピークが左)の場合は正(Sk>0)、その逆は負(Sk<0)の値を取るとのこと。歪度_180212

 個々の統計量は、当然Excel関数が準備されており、個別に算出することも可能です。それをまとめたのが以下の表です。RPythonの関数との比較もしています。基本統計量まとめ_180212 Excel関数の中で注意しなくてはならないのは、最頻値(mode関数)です(*1)。最頻値が複数ある場合は、「配列数式」を用いなくてはすべてを出力できません。つまり、下図のように、例えば、➀範囲を指定し、➁数式を入力し、➂Ctrl + Shift + Enterを押します。基本統計量4_180212 結果、2個目の最頻値の59も出力できました。3個目は#N/Aが出力されているので、このデータの最頻値は2個であることが分かります。基本統計量5_180212
 単純に「基本統計量」で求められた最頻値を鵜のみにしてしまうと、最頻値が複数ある場合に見落としてしまう可能性があります。要注意ですね。
 長くなりましたので、RPythonの「基本統計量」については、次回にお話しします。

ご訪問者数

(Since 24 July, 2016)

タグクラウド


プロフィール

Dr.BobT

Author: Dr.BobT
興味のおもむくままに生涯考え続けるエンジニアでありたい。

月別アーカイブ

メールフォーム

名前:
メール:
件名:
本文: