diff --git a/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java b/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java index d7638e9..b4649e6 100644 --- a/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java +++ b/src/main/java/info/istlab/Zemi01/numeric/NormalDistribution.java @@ -69,7 +69,7 @@ double d1 = 1.0 / Math.sqrt(2 * Math.PI * xvarp); double d2 = Math.exp(-Math.pow(x - xavg, 2) / (2 * xvarp)); double ret = d1 * d2 * 10000; - System.out.println(ret); + // System.out.println(ret); return ret; } @@ -87,7 +87,7 @@ xavg = Ttest.avg(dat); // 標準偏差を更新する xvarp = Ttest.varp(dat); - System.out.println("μ " + xavg + " σ^2 " + xvarp); + // System.out.println("μ " + xavg + " σ^2 " + xvarp); } diff --git a/src/main/java/info/istlab/Zemi01/numeric/WelchTtest.java b/src/main/java/info/istlab/Zemi01/numeric/WelchTtest.java new file mode 100644 index 0000000..02cb95d --- /dev/null +++ b/src/main/java/info/istlab/Zemi01/numeric/WelchTtest.java @@ -0,0 +1,415 @@ +package info.istlab.Zemi01.numeric; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Random; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import info.istlab.Zemi01.Launcher; +import info.istlab.Zemi01.miuramath.Ttest; + +/** + * 正規分布、ガウス分布 + */ + +public class WelchTtest extends JPanel implements MouseListener, MouseMotionListener, KeyListener { + + private static final long serialVersionUID = -919448575666487391L; + public static JFrame jf; + + /** + * @param args + */ + public static void main(String[] args) { + jf = new JFrame("正規分布、ガウス分布"); + jf.getContentPane().add(new WelchTtest()); + jf.pack(); + jf.setVisible(true); + jf.setLocation(Launcher.centerOfScreen(jf.getSize())); + + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + System.out.println("正規分布、ガウス分布 "); + System.out.println("つかいかた:(1)右クリックで、点を追加 (2)左ドラッグで、点移動 or グラフ移動 (3) 点の上で右クリックすると、点が消えます。"); + } + + Point2D offset; + + ND[] normdist = new ND[2]; + Dimension dim; + Point2D pointingPmath; + Point2D pressP; + static int psize = 10; + + public Dimension getPreferredSize() { + return dim; + } + + public WelchTtest() { + offset = new Point2D.Double(0, 100); + + dim = new Dimension(500, 400); + addMouseListener(this); + addMouseMotionListener(this); + addKeyListener(this); + this.setFocusable(true); + this.requestFocusInWindow(); + + normdist[0] = new ND(Color.blue, 0, 0); + normdist[1] = new ND(Color.green, 20, -30); + + setBackground(Color.white); + setForeground(Color.black); + + updateNormDist(); + + } + + public void paint(Graphics g) { + paintComponent(g); + } + + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHints(rh); + + // g2d.setBackground(Color.white); + // g2d.setColor(Color.black); + g2d.clearRect(0, 0, getWidth(), getHeight()); + + paintGrid(g2d); + + if (pointingPmath != null) { + g2d.setColor(Color.red); + paintPoint(g2d, pointingPmath); + } + + for (ND nd : normdist) { + nd.paintND(g2d, this); + } + + if (p2 < 0.05) { + g2d.setColor(Color.cyan); + } else { + g2d.setColor(Color.YELLOW); + } + for (int i = -2; i < 3; i++) + for (int j = -2; j < 3; j++) { + // g2d.drawRect(10, 50, 100, 10); + g2d.drawString("t (" + String.format("%4.2f", df2) + ") = " + String.format("%5.3f", welch_t), + (int) (-getWidth() / 2 + 30 - offset.getX() + i), + (int) (-getHeight() / 2 + 320 - offset.getY()) + j); + g2d.drawString("p = " + String.format("%5.3f", p2), + (int) (-getWidth() / 2 + 30 - offset.getX() + i), + (int) (-getHeight() / 2 + 345 - offset.getY()) + j); + } + if (p2 < 0.05) { + g2d.setColor(Color.blue); + } else { + g2d.setColor(Color.red); + } + // g2d.drawRect(10, 50, 100, 10); + g2d.drawString("t (" + String.format("%4.2f", df2) + ") = " + String.format("%5.3f", welch_t), + (int) (-getWidth() / 2 + 30 - offset.getX()), + (int) (-getHeight() / 2 + 320 - offset.getY())); + g2d.drawString("p = " + String.format("%5.3f", p2), + (int) (-getWidth() / 2 + 30 - offset.getX()), + (int) (-getHeight() / 2 + 345 - offset.getY())); + } + + private void updateNormDist() { + for (ND nd : normdist) { + nd.updateNormDist(); + } + updateTdist(); + } + + double welch_t; + double df2; + double p2; + + private void updateTdist() { + welch_t = Ttest.welch_t(normdist[1].data(), normdist[0].data()); + df2 = Ttest.welch_degree_of_freedom(normdist[1].data(), normdist[0].data()); + p2 = Ttest.tdist(welch_t, df2, 2); + // System.out.println("p2 = "+p2); + } + + public void paintPoint(Graphics2D g2d, Point2D p) { + g2d.setColor(Color.red); + g2d.fillOval((int) (p.getX() - WelchTtest.psize / 2), + (int) (-(p.getY() + WelchTtest.psize / 2)), WelchTtest.psize, WelchTtest.psize); + // g2d.drawString(String.valueOf(num), (int)p.getX()+10, (int)p.getY()); + } + + public void paintGrid(Graphics2D g2d) { + g2d.setColor(new Color(230, 230, 230)); + + g2d.translate(getWidth() / 2 + offset.getX(), getHeight() / 2 + offset.getY()); + // System.out.println(g2d.getTransform().getTranslateX()+" + // "+g2d.getTransform().getTranslateY()); + + for (int i = 0; i < getWidth(); i += 20) { + g2d.drawLine(i, -getHeight(), i, getHeight()); + g2d.drawLine(-i, -getHeight(), -i, getHeight()); + } + for (int i = 0; i < getHeight(); i += 20) { + g2d.drawLine(-getWidth(), i, getWidth(), i); + g2d.drawLine(-getWidth(), -i, getWidth(), -i); + } + g2d.setColor(Color.black); + g2d.drawLine(0, getHeight() * 3, 0, -getHeight() * 3); + g2d.drawLine(-getWidth() * 3, 0, getWidth() * 3, 0); + + // g2d.translate(-(getWidth()/2+offset.getX()), -(getHeight()/2+offset.getY())); + } + + public Point2D scr2math(Point2D p) { + double x = p.getX(); + double y = p.getY(); + x = x - offset.getX() - getWidth() / 2; + y = y - offset.getY() - getHeight() / 2; + y = -y; + // System.out.println("scr2math "+x+", "+y); + return new Point2D.Double(x, y); + } + + public Point2D math2scr(Point2D p) { + return new Point2D.Double(p.getX(), -p.getY()); + } + + public void mouseClicked(MouseEvent e) { + if (e.getButton() == 3) { + Point2D pointing = findPointing(e.getPoint()); + if (pointing == null) + normdist[0].points.add(scr2math(e.getPoint())); + else { + if (normdist[0].points.size() > 2) + normdist[0].points.remove(pointing); + } + updateNormDist(); + repaint(); + } + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public Point2D findPointing(Point2D mp) { + // Point2D nearest = null; + Point2D mPmath = scr2math(mp); + Point2D nP = null; + for (ND n : normdist) { + nP = n.nearestPoint(mPmath); + if (nP != null) + break; + } + return nP; + // pointingPmath = nP; + + // for (Point2D p : points) { + // if (mPmath.distance(p) < 8) { + // nearest = p; + // } + // } + // return nearest; + } + + public void mousePressed(MouseEvent e) { + mouseMoved(e); + } + + public void mouseReleased(MouseEvent e) { + pointingPmath = null; + repaint(); + } + + public void mouseDragged(MouseEvent e) { + if (pointingPmath != null) { + pointingPmath.setLocation(scr2math(e.getPoint())); + updateNormDist(); + repaint(); + } else { + // e.translatePoint((int)offset.getX(), (int)offset.getY()); + offset.setLocation(offset.getX() + (e.getPoint().getX() - pressP.getX()), + offset.getY() + (e.getPoint().getY() - pressP.getY())); + pressP = e.getPoint(); + updateNormDist(); + repaint(); + } + } + + public void mouseMoved(MouseEvent e) { + scr2math(e.getPoint()); + pressP = e.getPoint(); + Point2D pressPmath = scr2math(pressP); + Point2D nP = null; + for (ND n : normdist) { + nP = n.nearestPoint(pressPmath); + if (nP != null) + break; + } + pointingPmath = nP; + updateNormDist(); + repaint(); + } + + @Override + public void keyTyped(KeyEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + System.out.println(e.getKeyCode()); + + normdist[0] = new ND(Color.blue, 0, 0); + normdist[1] = new ND(Color.green, 20, -30); + updateNormDist(); + repaint(); + } + + } + + @Override + public void keyReleased(KeyEvent e) { + // TODO Auto-generated method stub + + } + +} + +class ND { + ArrayList points; + Color color; + int offsetx = 0; + int offsety = 0; + + public ND(Color c, int _offsetx, int _offsety) { + color = c; + offsetx = _offsetx; + offsety = _offsety; + points = new ArrayList(); + + Random rand = new Random(); + for (int i = 0; i < 7; i++) { + int randx = rand.nextInt(-40 + offsetx, 40 + offsetx); + int randy = rand.nextInt(-10 + offsety, offsety); + points.add(new Point2D.Double(randx, randy)); + } + updateNormDist(); + } + + double[] ddat; + + public double[] data() { + return ddat; + } + + // 平均と分散 + double xavg = 0; + double xvarp = 1; + + /** + * ガウス関数、ただし、μとσ^2は、xavg, xvarp から計算する + * + * @param x + * @return + */ + public double gauss_function(double x) { + double d1 = 1.0 / Math.sqrt(2 * Math.PI * xvarp); + double d2 = Math.exp(-Math.pow(x - xavg, 2) / (2 * xvarp)); + double ret = d1 * d2 * 10000; + // System.out.println(ret); + return ret; + } + + /** + * 点のx座標から、ガウス関数のパラメータ μとσ^2は、xavg, xvarp を更新する + */ + public void updateNormDist() { + ddat = new double[points.size()]; + int i = 0; + for (Point2D p : points) { + ddat[i] = p.getX(); + i++; + } + // 平均値を更新する + xavg = Ttest.avg(ddat); + // 標準偏差を更新する + xvarp = Ttest.varp(ddat); + // System.out.println("μ " + xavg + " σ^2 " + xvarp); + } + + public void paintND(Graphics2D g2d, WelchTtest wtest) { + + g2d.setColor(Color.black); + for (Point2D p : points) { + paintPoint(g2d, p); + } + + Point2D prep = null; + g2d.setColor(color); + for (double x = -wtest.getWidth() / 2 - wtest.offset.getX(); x < wtest.getWidth() / 2 + - wtest.offset.getX(); x += 1.0) { + Point2D p1 = wtest.math2scr(new Point2D.Double(x, gauss_function(x))); + if (prep == null) + prep = p1; + g2d.drawLine((int) p1.getX(), (int) p1.getY(), (int) prep.getX(), (int) prep.getY()); + prep = p1; + } + if (offsetx > 10) { + g2d.drawString("μ = " + String.format("%6.4f", xavg), (int) (wtest.getWidth() / 5 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 20 - wtest.offset.getY())); + g2d.drawString("σ = " + String.format("%6.4f", Math.sqrt(xvarp)), + (int) (wtest.getWidth() / 5 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 38 - wtest.offset.getY())); + g2d.drawString("σ^2 = " + String.format("%6.4f", xvarp), (int) (wtest.getWidth() / 5 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 56 - wtest.offset.getY())); + + } else { + g2d.drawString("μ = " + String.format("%6.4f", xavg), (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 20 - wtest.offset.getY())); + g2d.drawString("σ = " + String.format("%6.4f", Math.sqrt(xvarp)), + (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 38 - wtest.offset.getY())); + g2d.drawString("σ^2 = " + String.format("%6.4f", xvarp), (int) (-wtest.getWidth() / 2 + 10 - wtest.offset.getX()), + (int) (-wtest.getHeight() / 2 + 56 - wtest.offset.getY())); + } + + } + + public void paintPoint(Graphics2D g2d, Point2D p) { + g2d.fillOval((int) (p.getX() - WelchTtest.psize / 2), + (int) (-(p.getY() + WelchTtest.psize / 2)), WelchTtest.psize, WelchTtest.psize); + // g2d.drawString(String.valueOf(num), (int)p.getX()+10, (int)p.getY()); + } + + public Point2D nearestPoint(Point2D pressPmath) { + Point2D nearest = null; + for (Point2D p : points) { + if (pressPmath.distance(p) < 8) { + nearest = p; + } + } + return nearest; + } + +}