火曜日, 12月 01, 2015

Javaの関数プログラミングで偏差

暇つぶしに統計の基礎の動画を見ていたら,サンプルのコードを書きたくなったので,メモとして..
この例ではカンマ区切りの名前と点数 の行からなるデータを読み込んで,平均,分散,偏差,標準偏差そして偏差値を計算する.

package org.tanuneko;

import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.stream.Stream;

public class STDDev {

    public static void main(String args[]) throws Exception {
        new STDDev();
    }

    public STDDev() throws IOException {
        File scoreFile = new File(STDDev.class.getClassLoader().getResource("score.txt").getPath());
        ImmutableList<Record> rec = Files.asCharSource(scoreFile, Charset.defaultCharset())
                .readLines(new LineProcessor<ImmutableList<Record>>() {
                    List<Record> results = Lists.newArrayList();
                    @Override
                    public boolean processLine(String line) throws IOException {
                        List<String> elems = Splitter.on(",").splitToList(line);
                        Preconditions.checkState(elems.size() == 2);
                        results.add(new Record(elems.get(0), Integer.parseInt(elems.get(1))));
                        return true;
                    }

                    @Override
                    public ImmutableList<Record> getResult() {
                        return ImmutableList.copyOf(results);
                    }
                });

        int totalScore = rec.stream().mapToInt(x->x.getScore()).sum();
        double avg = totalScore / rec.size();
        rec.stream().forEach(x->x.setDev(x.getScore() - avg));
        double v = calcVariation(rec);
        double d = calcStddev(rec);

        System.out.println("total:" + totalScore + ", avg:" + avg);
        System.out.println("variation:" + v);
        System.out.println("stddev:" + d);
        System.out.println(checkDev(rec));

        rec.stream().forEach(x -> {
            x.setScoreDev(50 + 10 * (x.getDev()/d));
        });

        System.out.println(rec);
    }

    private double calcVariation(ImmutableList<Record> rec) {
        return rec.stream().mapToDouble(x->x.getDev())
                .reduce(0, (x,y)-> x + Math.pow(y, 2)) / rec.size();
    }

    private double calcStddev(ImmutableList<Record> rec) {
        return Math.sqrt(calcVariation(rec));
    }

    private boolean checkDev(ImmutableList<Record> rec) {
        double d = rec.stream().mapToDouble(x->x.getDev())
                .sum();
        System.out.println(d);
        return d == 0;
    }
}

class Record {
    private String name;
    private int score;
    private double dev;
    private double scoreDev;
    public Record(String name, int score) {
        this.name = name;
        this.score = score;
        dev = scoreDev = 0d;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("name", name)
                .add("score", score)
                .add("dev", dev)
                .add("score dev", scoreDev)
                .toString();
    }

    public int getScore() {
        return score;
    }

    public double getDev() {
        return dev;
    }

    public void setDev(double dev) {
        this.dev = dev;
    }

    public double getScoreDev() {
        return scoreDev;
    }

    public void setScoreDev(double scoreDev) {
        this.scoreDev = scoreDev;
    }
}



0 件のコメント: