num4normality 0.0.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6be725c6a9b20d5c4ca46f2543c96e293be67c9bcf2638816cb29331eadb8180
4
+ data.tar.gz: d18160bcab51e0760a2e4b533be709235f06d18b2150bb05cc4a9ef66a96179f
5
+ SHA512:
6
+ metadata.gz: 1e9c798eaa8043b712da5940f361c8adffa82f4436cccc34843286baad3109d481354fea2a8f6f914f4f8205f2ff0393c31f47cdde589cdb408506257ba06491
7
+ data.tar.gz: 9f257c671f62f84c224a03641d802d7f275a6d042c80d336f4a666283def61b53a169527c6ec854676ff3344da8e60bcb2a0e6716b8afa8e31d700172d91fed2
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Change Log
2
+
3
+ ## Unreleased
4
+
5
+ ## [0.0.1] - 2023-12-05
6
+
7
+ ### Fixed
8
+ - fix first fixed.
9
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 siranovel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/javaextensiontask'
2
+
3
+ jars = Dir.glob("lib/*.jar")
4
+ Rake::JavaExtensionTask.new(name='num4normality') do | ext |
5
+ ext.release = '11'
6
+ ext.classpath = jars.map { |x| File.expand_path x }.join ":"
7
+ end
8
+ task :default => [:compile]
@@ -0,0 +1,313 @@
1
+ import org.jfree.chart.JFreeChart;
2
+ import org.jfree.chart.StandardChartTheme;
3
+ import org.jfree.chart.ChartFactory;
4
+ import org.jfree.data.xy.XYSeriesCollection;
5
+ import org.jfree.data.xy.XYSeries;
6
+
7
+ import org.jfree.chart.plot.XYPlot;
8
+ import org.jfree.chart.axis.NumberAxis;
9
+ import org.jfree.chart.axis.ValueAxis;
10
+ import org.jfree.chart.plot.PlotOrientation;
11
+ import org.jfree.chart.axis.NumberTickUnit;
12
+ import org.jfree.chart.labels.XYToolTipGenerator;
13
+ import org.jfree.chart.labels.StandardXYToolTipGenerator;
14
+ import org.jfree.chart.renderer.xy.XYItemRenderer;
15
+ import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
16
+ import org.jfree.chart.plot.DatasetRenderingOrder;
17
+
18
+ import org.jfree.chart.ChartUtils;
19
+ import java.io.File;
20
+ import java.io.IOException;
21
+
22
+ import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
23
+ import org.apache.commons.math3.distribution.NormalDistribution;
24
+ import java.util.Arrays;
25
+ import java.text.DecimalFormat;
26
+ public class Normality {
27
+ public static void qqplot(String dname, double[] xi) {
28
+ ChartPlot plot = new QQPlot();
29
+ JFreeChart chart = plot.createChart(dname, xi);
30
+
31
+ plot.writeJPEG("qqplot.jpeg", chart, 800, 500);
32
+ }
33
+ public static void kstest(String dname, double[] xi) {
34
+ ChartPlot plot = new KSTest();
35
+ JFreeChart chart = plot.createChart(dname, xi);
36
+
37
+ plot.writeJPEG("kstest.jpeg", chart, 800, 500);
38
+
39
+ }
40
+ public static boolean skewnesstest(double[] xi) {
41
+ DAgostinosTest daigo = new SkewnessTest();
42
+
43
+ double b1 = daigo.calcTestStatistic(xi);
44
+ return daigo.test(b1, 0.05);
45
+ }
46
+ public static boolean kurtosistest(double[] xi) {
47
+ DAgostinosTest daigo = new KurtosisTest();
48
+
49
+ double b2 = daigo.calcTestStatistic(xi);
50
+ return daigo.test(b2, 0.05);
51
+ }
52
+
53
+
54
+ private interface ChartPlot {
55
+ JFreeChart createChart(String dname, double[] xi);
56
+ default void writeJPEG(String fname, JFreeChart chart, int width, int height) {
57
+ File file = new File(fname);
58
+ try {
59
+ ChartUtils.saveChartAsJPEG(file, chart, width, height);
60
+ } catch (IOException e) {
61
+ e.printStackTrace();
62
+ }
63
+ }
64
+ }
65
+ private interface DAgostinosTest {
66
+ double calcTestStatistic(double[] xi);
67
+ boolean test(double statistic, double a);
68
+ }
69
+
70
+ // Q-Qplot
71
+ private static class QQPlot implements ChartPlot {
72
+ private DescriptiveStatistics stat = null;
73
+ private double m = 0.0;
74
+ private double sd = 0.0;
75
+ public QQPlot() {
76
+ stat = new DescriptiveStatistics();
77
+ }
78
+ public JFreeChart createChart(String dname, double[] xi) {
79
+ Arrays.stream(xi).forEach(stat::addValue);
80
+ m = stat.getMean(); // 平均
81
+ sd = stat.getStandardDeviation();// 標準偏差
82
+
83
+ XYPlot plot = createPlot(dname, xi);
84
+ /*--- 横軸 ---*/
85
+ NumberAxis domainAxis = new NumberAxis("標準正規分布");
86
+
87
+ plot.setDomainAxis(domainAxis);
88
+ domainAxis.setLowerMargin(0.03);
89
+ domainAxis.setUpperMargin(0.03);
90
+ domainAxis.setLowerBound(-4);
91
+ domainAxis.setUpperBound(4);
92
+
93
+ ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme());
94
+ return new JFreeChart("正規性の検定", plot);
95
+ }
96
+ private XYPlot createPlot(String dname, double[] xi) {
97
+ XYItemRenderer renderer0 = new XYLineAndShapeRenderer(false, true);
98
+ XYItemRenderer renderer1 = new XYLineAndShapeRenderer(true, false);
99
+ XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
100
+
101
+ renderer0.setDefaultToolTipGenerator(toolTipGenerator);
102
+ renderer0.setURLGenerator(null);
103
+ renderer1.setDefaultToolTipGenerator(toolTipGenerator);
104
+ renderer1.setURLGenerator(null);
105
+
106
+ XYPlot plot = new XYPlot();
107
+ plot.setOrientation(PlotOrientation.VERTICAL);
108
+ plot.mapDatasetToRangeAxis(0,0);
109
+ plot.mapDatasetToRangeAxis(1,0);
110
+ plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
111
+
112
+ /*--- 縦軸 ---*/
113
+ NumberAxis valueAxis0 = new NumberAxis("観測値");
114
+ plot.setRangeAxis(valueAxis0);
115
+
116
+ plot.setRenderer(0, renderer0);
117
+ plot.setDataset(0, createDataset0(dname, xi));
118
+
119
+ plot.setRenderer(1, renderer1);
120
+ plot.setDataset(1, createDataset1());
121
+
122
+ return plot;
123
+ }
124
+ private XYSeriesCollection createDataset0(String dname, double[] xi) {
125
+ double den = sd / Math.sqrt(xi.length);
126
+ XYSeries series = new XYSeries(dname);
127
+
128
+ for (int i = 0; i < xi.length; i++) {
129
+ double x = (xi[i] - m) / den;
130
+
131
+ series.add(x, xi[i]);
132
+ }
133
+ XYSeriesCollection data = new XYSeriesCollection();
134
+
135
+ data.addSeries(series);
136
+ return data;
137
+ }
138
+ private XYSeriesCollection createDataset1() {
139
+ XYSeries series = new XYSeries("累積");
140
+ NormalDistribution ndist = new NormalDistribution(0, 1);
141
+
142
+ for (double p = 0.001; p < 1.0; p += 0.01) {
143
+ double x = ndist.inverseCumulativeProbability(p);
144
+
145
+ series.add(x, x * sd + m);
146
+ }
147
+
148
+ XYSeriesCollection data = new XYSeriesCollection();
149
+ data.addSeries(series);
150
+ return data;
151
+ }
152
+ }
153
+ // コルモゴルフ・スミルノフ検定
154
+ private static class KSTest implements ChartPlot {
155
+ private NormalDistribution ndist = null;
156
+ public KSTest() {
157
+ ndist = new NormalDistribution(0, 1);
158
+ }
159
+ public JFreeChart createChart(String dname, double[] xi) {
160
+ NumberAxis domainAxis = new NumberAxis("標準正規分布");
161
+ XYPlot plot = createPlot(dname, xi);
162
+
163
+ /*--- 横軸 ---*/
164
+ plot.setDomainAxis(domainAxis);
165
+ domainAxis.setLowerMargin(0.03);
166
+ domainAxis.setUpperMargin(0.03);
167
+ domainAxis.setLowerBound(-4);
168
+ domainAxis.setUpperBound(4);
169
+
170
+ ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme());
171
+ return new JFreeChart("コルモゴルフ・スミルノフ検定", plot);
172
+ }
173
+ private XYPlot createPlot(String dname, double[] xi) {
174
+ XYItemRenderer renderer0 = new XYLineAndShapeRenderer(false, true);
175
+ XYItemRenderer renderer1 = new XYLineAndShapeRenderer(true, false);
176
+ XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
177
+
178
+ renderer0.setDefaultToolTipGenerator(toolTipGenerator);
179
+ renderer0.setURLGenerator(null);
180
+ renderer1.setDefaultToolTipGenerator(toolTipGenerator);
181
+ renderer1.setURLGenerator(null);
182
+
183
+ XYPlot plot = new XYPlot();
184
+ plot.setOrientation(PlotOrientation.VERTICAL);
185
+ plot.mapDatasetToRangeAxis(0,0);
186
+ plot.mapDatasetToRangeAxis(1,0);
187
+ plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
188
+
189
+ /*--- 縦軸 ---*/
190
+ NumberAxis valueAxis0 = new NumberAxis("確率");
191
+ plot.setRangeAxis(valueAxis0);
192
+ valueAxis0.setLowerBound(0);
193
+ valueAxis0.setUpperBound(1);
194
+ valueAxis0.setTickUnit(new NumberTickUnit(0.1));
195
+ valueAxis0.setNumberFormatOverride(new DecimalFormat("0.0#"));
196
+
197
+ plot.setRenderer(0, renderer0);
198
+ plot.setDataset(0, createDataset0(dname, xi));
199
+
200
+ plot.setRenderer(1, renderer1);
201
+ plot.setDataset(1, createDataset1());
202
+
203
+ return plot;
204
+ }
205
+ private XYSeriesCollection createDataset0(String dname, double[] xi) {
206
+ Arrays.sort(xi);
207
+ DescriptiveStatistics stat = new DescriptiveStatistics();
208
+ Arrays.stream(xi).forEach(stat::addValue);
209
+ double m = stat.getMean(); // 平均
210
+ double sd = stat.getStandardDeviation();// 標準偏差
211
+ double den = sd / Math.sqrt(xi.length);
212
+ double sum = stat.getSum();
213
+ double p = 0.0;
214
+
215
+ XYSeries series = new XYSeries(dname);
216
+ for (int n = 0; n < xi.length; n++) {
217
+ double x = (xi[n] - m) / den;
218
+
219
+ p += xi[n] / sum;
220
+ series.add(x, p);
221
+ }
222
+ XYSeriesCollection data = new XYSeriesCollection();
223
+
224
+ data.addSeries(series);
225
+ return data;
226
+ }
227
+ private XYSeriesCollection createDataset1() {
228
+ XYSeries series = new XYSeries("累積");
229
+
230
+ for (double x = -4; x < 4; x += 0.01) {
231
+ double y = ndist.cumulativeProbability(x);
232
+
233
+ series.add(x, y);
234
+ }
235
+ XYSeriesCollection data = new XYSeriesCollection();
236
+
237
+ data.addSeries(series);
238
+ return data;
239
+ }
240
+ }
241
+ // タコスディーノ検定(歪度)
242
+ private static class SkewnessTest implements DAgostinosTest {
243
+ private long n = 0;
244
+ private NormalDistribution ndist = null;
245
+ public SkewnessTest() {
246
+ ndist = new NormalDistribution(0, 1);
247
+ }
248
+ public double calcTestStatistic(double[] xi) {
249
+ DescriptiveStatistics stat = new DescriptiveStatistics();
250
+
251
+ Arrays.stream(xi).forEach(stat::addValue);
252
+ n = stat.getN();
253
+ return Math.sqrt(stat.getSkewness());
254
+ }
255
+
256
+ public boolean test(double statistic, double a) {
257
+ double ua_2 = ndist.inverseCumulativeProbability(1.0 - a);
258
+
259
+ return (Math.abs(statistic) > cnvb2tob2p(ua_2))
260
+ ? true : false;
261
+ }
262
+ private double cnvb2tob2p(double ua_2) {
263
+ double el = (n + 1.0) * (n + 1.0) * (n + 3.0) * (n + 5.0); // 分子
264
+ double den = 24 * n * (n - 2.0) * (n - 3.0); // 分母
265
+ double b2p = Math.sqrt(el / den) *
266
+ (long)(ua_2 + 3.0 / (2.0 * n) * (ua_2 * ua_2 * ua_2 - 3 * ua_2));
267
+
268
+ return b2p;
269
+ }
270
+ }
271
+ // タコスディーノ検定(尖度)
272
+ private static class KurtosisTest implements DAgostinosTest {
273
+ private long n = 0;
274
+ private NormalDistribution ndist = null;
275
+ public KurtosisTest() {
276
+ ndist = new NormalDistribution(0, 1);
277
+ }
278
+ public double calcTestStatistic(double[] xi) {
279
+ DescriptiveStatistics stat = new DescriptiveStatistics();
280
+
281
+ Arrays.stream(xi).forEach(stat::addValue);
282
+ n = stat.getN();
283
+
284
+ return stat.getKurtosis();
285
+ }
286
+ public boolean test(double statistic, double a) {
287
+ boolean ret = false;
288
+ double ua_2 = ndist.inverseCumulativeProbability(1.0 - a);
289
+ double b2p = cnvb2tob2p(statistic);
290
+
291
+ double r_val = ua_2 + Math.sqrt(6.0 / n) * (ua_2 * ua_2 - 1.0);
292
+ double l_val = -1.0 * ua_2 + Math.sqrt(6.0 / n) * (ua_2 * ua_2 - 1.0);
293
+
294
+ if (b2p > r_val) {
295
+ ret = true;
296
+ }
297
+ if (b2p < l_val) {
298
+ ret = true;
299
+ }
300
+ return ret;
301
+ }
302
+ private double cnvb2tob2p(double b2) {
303
+ double el = (n + 1.0) * (n + 1.0) * (n + 3.0) * (n + 5.0); // 分子
304
+ double den = 24 * n * (n - 2.0) * (n - 3.0); // 分母
305
+
306
+ double b2p = Math.sqrt(el / den) *
307
+ (long)(b2 - 3 * (n - 1.0) / (n + 3.0));
308
+
309
+ return b2p;
310
+ }
311
+ }
312
+ }
313
+
Binary file
Binary file
Binary file
@@ -0,0 +1,68 @@
1
+ require 'java'
2
+ require 'num4normality.jar'
3
+ require 'jfreechart-1.5.4.jar'
4
+ require 'commons-math3-3.6.1.jar'
5
+
6
+ java_import 'Normality'
7
+
8
+ # 正規性の検定
9
+ # (Apache commoms math3使用)
10
+ module Num4NormalityLib
11
+ class << self
12
+ # Q-Qプロット
13
+ #
14
+ # @overload qqplot(dname, xi)
15
+ # @param [String] dname データ名
16
+ # @param [Array] xi データ(double[])
17
+ # @return [void] qqplot.jpegファイルを出力
18
+ # @example
19
+ # xi = [320, 240, 402, 325, 440, 286, 362, 281, 560, 212, 198, 209]
20
+ # Num4NormalityLib.qqplot("LDH", xi)
21
+ # => qqplot.jpeg
22
+ # @note
23
+ # グラフは、jfreechartを使用
24
+ def qqplot(dname, xi)
25
+ Normality.qqplot(dname, xi.to_java(Java::double))
26
+ end
27
+ # コルモゴルフ・スミルノフ検定
28
+ #
29
+ # @overload kstest(dname, xi)
30
+ # @param [String] dname データ名
31
+ # @param [Array] xi データ(double[])
32
+ # @return [void] kstest.jpegファイルを出力
33
+ # @example
34
+ # xi = [320, 240, 402, 325, 440, 286, 362, 281, 560, 212, 198, 209]
35
+ # Num4NormalityLib.kstest("LDH", xi)
36
+ # => kstest.jpeg
37
+ # @note
38
+ # グラフは、jfreechartを使用
39
+ def kstest(dname, xi)
40
+ Normality.kstest(dname, xi.to_java(Java::double))
41
+ end
42
+ # タコスディーノ検定(歪度)
43
+ #
44
+ # @overload skewnesstest(xi)
45
+ # @param [Array] xi データ(double[])
46
+ # @return [boolean] 検定結果(true:棄却域内 false:棄却域外)
47
+ # @example
48
+ # xi = [320, 240, 402, 325, 440, 286, 362, 281, 560, 212, 198, 209]
49
+ # Num4NormalityLib.skewnesstest(xi)
50
+ # => false
51
+ def skewnesstest(xi)
52
+ Normality.skewnesstest(xi.to_java(Java::double))
53
+ end
54
+ # タコスディーノ検定(尖度)
55
+ #
56
+ # @overload kurtosistest(xi)
57
+ # @param [Array] xi データ(double[])
58
+ # @return [boolean] 検定結果(true:棄却域内 false:棄却域外)
59
+ # @example
60
+ # xi = [320, 240, 402, 325, 440, 286, 362, 281, 560, 212, 198, 209]
61
+ # Num4NormalityLib.kurtosistest(xi)
62
+ # => false
63
+ def kurtosistest(xi)
64
+ Normality.kurtosistest(xi.to_java(Java::double))
65
+ end
66
+ end
67
+ end
68
+
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: num4normality
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: java
6
+ authors:
7
+ - siranovel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 12.3.3
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '12.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 12.3.3
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake-compiler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.5
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.2.5
53
+ description: numerical solution for test of normality.
54
+ email: siranovel@gmail.com
55
+ executables: []
56
+ extensions:
57
+ - Rakefile
58
+ extra_rdoc_files: []
59
+ files:
60
+ - CHANGELOG.md
61
+ - Gemfile
62
+ - LICENSE
63
+ - Rakefile
64
+ - ext/num4normality/Normality.java
65
+ - lib/commons-math3-3.6.1.jar
66
+ - lib/jcommon-1.0.23.jar
67
+ - lib/jfreechart-1.5.4.jar
68
+ - lib/num4normality.rb
69
+ homepage: http://github.com/siranovel/num4normality
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.3.7
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: num for normality
92
+ test_files: []