0

私はテキストファイルを持っています:

DATE 20090105
1 2.25 1.5
3 3.6 0.099
4 3.6 0.150
6 3.6 0.099
8 3.65 0.0499
DATE 20090105
DATE 20090106
1 2.4 1.40
2 3.0 0.5
5 3.3 0.19
7 2.75 0.5
10 2.75 0.25
DATE 20090106
DATE 20090107
2 3.0 0.5
2 3.3 0.19
9 2.75 0.5
DATE 20100107

毎日私は持っています:

Time Rating Variance

最大の時間スケールで特定の時間の平均分散を計算したいと考えています。

ファイルは巨大で、これは編集された小さなサンプルです。これは、最新時刻と最古時刻 (2600 前後) がわからず、最新時刻が 50000 前後である可能性があることを意味します。

たとえば、すべての日に時間 t=1 で値が 1 つしかないため、それがその時点での平均分散です。

時間 t=2 では、最初の日、時間 t=2 での分散は t=3 まで続くため値 1.5 を取り、2 日目には値=0.5 を取り、3 日目には値 ((0.5+ 0.18)/2)。したがって、時間 t=2 でのすべての日の平均分散は、その時点でのすべての分散の合計を、その時点での異なる分散の数で割ったものです。

1 日の最後の時間の時間スケールは t=1 です。

私はこれについてどうやって行くのだろうかと思っています。

完全な初心者として、私はこれがかなり複雑だと感じています。私は大学の学生ですが、大学は卒業しており、夏の間、父の仕事を手伝うために Java を学ぼうとしています。したがって、ソリューションに関するヘルプは大歓迎です。

4

4 に答える 4

0

私があなたを正しく理解しているなら、あなたはデータの流れで計算された移動平均を求めています。私が書いた次のクラスは、そのような統計を提供します。

  • 移動平均
  • 減衰平均(減衰係数に基づいて、最後のいくつかのサンプルの平均を反映します)。
  • 移動分散
  • 減衰分散
  • 最小および最大

それが役に立てば幸い。

/**
 * omry 
 * Jul 2, 2006
 * 
 * Calculates:
 * 1. running average 
 * 2. running standard deviation.
 * 3. minimum
 * 4. maximum
 */
public class Statistics
{
    private double m_lastValue;
    private double m_average = 0;
    private double m_stdDevSqr = 0;

    private int m_n = 0;
    private double m_max = Double.NEGATIVE_INFINITY;
    private double m_min = Double.POSITIVE_INFINITY;

    private double m_total;

    // decay factor.
    private double m_d;
    private double m_decayingAverage;
    private double m_decayingStdDevSqr;

    public Statistics()
    {
        this(2);
    }

    public Statistics(float d)
    {
        m_d = d;
    }

    public void addValue(double value)
    {
        m_lastValue = value;
        m_total += value;

        // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
        m_n++;
        double delta = value - m_average;
        m_average = m_average + delta / (float)m_n;
        double md = (1/m_d);
        if (m_n == 1)
        {
            m_decayingAverage = value;
        }
        m_decayingAverage = (md * m_decayingAverage + (1-md)*value);

        // This expression uses the new value of mean
        m_stdDevSqr = m_stdDevSqr + delta*(value - m_average);

        m_decayingStdDevSqr = m_decayingStdDevSqr + delta*(value - m_decayingAverage);

        m_max = Math.max(m_max, value);
        m_min = Math.min(m_min, value);     
    }

    public double getAverage()
    {
        return round(m_average);
    }

    public double getDAverage()
    {
        return round(m_decayingAverage);
    }   

    public double getMin()
    {
        return m_min;
    }

    public double getMax()
    {
        return m_max;
    }

    public double getVariance()
    {
        if (m_n > 1)
        {
            return round(Math.sqrt(m_stdDevSqr/(m_n - 1)));
        }
        else
        {
            return 0;
        }
    }


    public double getDVariance()
    {
        if (m_n > 1)
        {
            return round(Math.sqrt(m_decayingStdDevSqr/(m_n - 1)));
        }
        else
        {
            return 0;
        }
    }

    public int getN()
    {
        return m_n;
    }

    public double getLastValue()
    {
        return m_lastValue;
    }

    public void reset()
    {
        m_lastValue = 0;
        m_average = 0;
        m_stdDevSqr = 0;
        m_n = 0;
        m_max = Double.NEGATIVE_INFINITY;
        m_min = Double.POSITIVE_INFINITY;
        m_decayingAverage = 0;
        m_decayingStdDevSqr = 0;
        m_total = 0;
    }

    public double getTotal()
    {
        return round(m_total);
    }

    private double round(double d)
    {
        return Math.round((d * 100))/100.0;
    }
}
于 2010-07-13T14:15:00.363 に答える
0

わかりました、私は動作するコードを持っています。しかし、ループを何度も繰り返す必要があるため、非常に長い時間がかかります (1 日あたり約 7 か月分、1 日あたり 30,000 の分散があります)。他に良い提案はありますか?

このコードは、一見単純に見えるものの、約 24 ~ 28 時間かかることを意味します...

パッケージ VarPackage;

java.io.BufferedReader をインポートします。java.io.FileReader をインポートします。import java.util.ArrayList;

パブリック クラス ReadText {

public static void main(String[] args) throws Exception {
    String inputFileName="C:\\MFile";


    ArrayList<String> fileLines = new ArrayList<String>();
    FileReader fr;
    BufferedReader br;

    // Time
    int t = 1;


    fr = new FileReader(inputFileName);
    br = new BufferedReader(fr);
    String line;


    while ((line=br.readLine())!=null) {
     fileLines.add(line);
    }

    AvgVar myVar = new AvgVar(fileLines);

    for(t=1; t<10; t++){ 
    System.out.print("Average Var at Time t=" + t + " = " + myVar.avgVar(t)+"\n");

}

} }

===================================

新しいクラス

パッケージ VarPackage;

import java.util.ArrayList;

public class AvgVar { // クラス変数 private ArrayList inputData = new ArrayList();

// コンストラクタ AvgVar(ArrayList fileData){ inputData = fileData; }

public double avgVar(int time){

 double avgVar = 0;

 ArrayList<double[]> avgData = avgDuplicateVars(inputData);

 for(double[] arrVar : avgData){
 avgVar += arrVar[time-1];
 //System.out.print(arrVar[time-1] + "," + arrVar[time] + "," + arrVar[time+1] + "\n");
 //System.out.print(avgVar + "\n");
 }

 avgVar /= numDays(inputData);

 return avgVar;
}

private int numDays(ArrayList<String> varData){

 int n = 0;
 int flag = 0;

for(文字列 : varData){

String[] myData = line.split(" ");

if(myData[0].equals("DATE") && flag == 0){

    flag = 1;

   }
   else if(myData[0].equals("DATE") && flag == 1){

    n = n + 1;
    flag = 0;

   }

}

n を返します。

}

private ArrayList<double[]> avgDuplicateVars(ArrayList<String> varData){

 ArrayList<double[]> avgData = new ArrayList<double[]>();

 double[] varValue = new double[86400];
 double[] varCount = new double[86400];

 int n = 0;
 int flag = 0;

for(String iLine : varData){

String[] nLine = iLine.split(" ");
   if(nLine[0].equals("DATE") && flag == 0){

    for (int i=0; i<86400; i++){
    varCount[i] = 0;
    varValue[i] = 0;
    }

    flag = 1;

   }
   else if(nLine[0].equals("DATE") && flag == 1){

    for (int i=0; i<86400; i++){
    if (varCount[i] != 0){
    varValue[i] /= varCount[i];
    }
    }

    varValue = fillBlankSpreads(varValue, 86400);

    avgData.add(varValue.clone());

    flag = 0;

   }
   else{

    n = Integer.parseInt(nLine[0])-1;

    varValue[n] += Double.parseDouble(nLine[2]);
    varCount[n] += 1;

   }

}

avgData を返します。

}

private double[] fillBlankSpreads(double[] varValue, int numSpread){
//Filling the Data with zeros to make the code faster
 for (int i=1; i<numSpread; i++){
 if(varValue[i] == 0){
 varValue[i] = varValue[i-1];
 }
 }

 return varValue;
}

}

于 2010-07-14T13:15:02.410 に答える
0

分かったと思う。あなたはしたい

  1. t各日の特定の時間における平均分散を見つけます。これは、その日の最も高いタイムスタンプによって与えられます。t
  2. それらを平均化することにより、同時に複数の読み取りが発生する場合に対処します。
  3. すべての日の平均分散を特定するt

したがって、@Manjoorが提案したようにデータを解析したら、(疑似コード!)

function getAverageAt(int t)
  float lastvariance = 0; // what value to start on, 
                        // if no variance is specified at t=1 on day 1
                        // also acts as accumulator if several values at one 
                        // timestamp
  float allDaysTotal = 0; // cumulative sum of the variance at time t for all days
  for each day {
    float time[], rating[], variance[];
    //read these from table
    int found=0; //how many values found at time t today
    for(int i=0;i<time.length;i++){
       if(time[i]<t) lastvariance=variance[i];  // find the most recent value
                        // before t.
                        // This relies on your data being in order!
       else if(time[i]==t){  // time 
         found++;
         if (found==1) lastvariance=variance[i]; // no previous occurrences today
         else lastvariance+=variance[i];
       }
       else if(time[i]>t) break;
    }
    if(found>1) lastvariance/=found;  // calculate average of several simultaneous
    // readings, if more than one value found today at time t.
    // Note that: if found==0, this means you're using a previous
    // timestamp's value.
    // Also note that, if at t=1 you have 2 values of variance, that 
    // averaged value will not continue over to time t. 
    // You could easily reimplement that if that's the behaviour you desire,
    // the code is similar, but putting the time<t condition along with the 
    // time==t condition 
    allDaysTotal+=lastvariance;
  }
  allDaysMean = allDaysTotal / nDays

私が指摘したキャッチケースが示すように、あなたの問題は単純なものではありません。

于 2010-07-14T10:42:18.660 に答える
0

以下の手順に従う必要があります

  • date と trv プロパティを持つクラスを作成する
  • 上記のクラスのリストを作成する
  • IO クラスを使用してファイルを読み取ります。
  • チャンクで読み取り、文字列に変換する
  • 文字列全体を「DATE」で分割してトリム
  • スペース (" ") で分割
  • 最初の項目はあなたの日付です。
  • 他のすべての項目を浮動小数点数に変換し、平均を見つけます。
  • リストに追加します。これで、毎日の平均のリストができました。
  • ディスクに永続化し、必要なデータを照会できます。

編集 質問を編集しましたが、今ではまったく異なって見えます。ファイルの解析に助けが必要だと思います。私が間違っている場合は修正してください。

于 2010-07-13T14:05:32.170 に答える