Удельное среднее время Java

У меня есть текстовый файл:

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.

Так, например, во все дни у меня есть только 1 значение во время t = 1, следовательно, это средняя дисперсия в то время.

В момент времени t=2 в первый день дисперсия в момент времени t=2 принимает значение 1,5, так как она длится до t=3, во второй день принимает значение =0,5, а в третий день принимает значение ((0,5+ 0,18)/2). Таким образом, средняя дисперсия за все дни в момент времени t=2 представляет собой сумму всех дисперсий в это время, деленную на количество различных дисперсий в это время.

В последний раз в день масштаб времени, который требуется, равен t=1.

Мне просто интересно, как бы я вообще поступил с этим.

Как полный новичок, я нахожу это довольно сложным. Я студент универа, но университет закончился, и я пытаюсь выучить Java, чтобы помочь папе в бизнесе летом. Поэтому любая помощь в отношении решений приветствуется.


person Sam Hank    schedule 13.07.2010    source источник
comment
Я думаю, что вы не получаете ответов, потому что описание вашей проблемы трудно понять. Пожалуйста, постарайтесь сделать это немного понятнее для нас, простых смертных!   -  person Carl Smotricz    schedule 13.07.2010
comment
Кроме того, какой результат вы ожидаете? Вы хотите записать файл с вариациями для каждого возможного времени? Или вы будете запрашивать определенное время и хотите найти или вычислить ответы в это время?   -  person Carl Smotricz    schedule 13.07.2010
comment
7-го числа ваш первый раз равен 2. Итак, как должна выглядеть ваша дисперсия в момент 1?   -  person Carl Smotricz    schedule 13.07.2010
comment
Дисперсия в момент времени 1 равна 0 для 7-го числа, и это должно вносить вклад в среднее значение, т. Е. Для времени t = 1 среднее значение будет (1,5 + 1,4 + 0) / 3. Но в течение дня, если дисперсия не объявляется в определенное время, это происходит потому, что для дисперсии по-прежнему принимается последнее значение во времени.   -  person Sam Hank    schedule 13.07.2010


Ответы (4)


Вы должны выполнить следующие шаги

  • Создайте класс с датой и свойством trv
  • Создать список выше класса
  • Прочитайте файл, используя классы ввода-вывода.
  • Читать кусками и преобразовывать в строку
  • Разделить всю строку на «DATE» и обрезать
  • Разделить пробелом ("")
  • Первым пунктом будет ваша дата.
  • Преобразуйте все остальные элементы в число с плавающей запятой и найдите среднее значение.
  • Добавьте его в список. Теперь у вас есть список дневных средних значений.
  • Вы можете сохранить его на диск и запросить необходимые данные.

РЕДАКТИРОВАТЬ, вы отредактировали свой вопрос, и теперь он выглядит совершенно по-другому. Я думаю, вам нужна помощь в разборе файла. Поправьте меня, если я ошибаюсь.

person Manjoor    schedule 13.07.2010
comment
Спасибо за ваш ответ, но я не думаю, что это совсем то, что мне нужно. Мне нужно среднее значение в это конкретное время за все дни. Например. ПОНЕДЕЛЬНИК Люди в магазине 9:00 5 9:05 10 9:10 15 Вторник 9:00 1 9:05 2 9:10 1 Таким образом, средняя модель, предсказывающая, сколько людей будет в магазине в это время, приведена ниже. 9:00 3 9:05 6 9:10 8 Поскольку я взял среднее количество людей в магазине в это время. Я думаю, то, что вы описываете, это просто среднесуточная норма? Спасибо - person Sam Hank; 13.07.2010
comment
Затем вам нужно разобрать файл и передать данные в базу данных (например, mySQL). Затем вы можете запросить его, используя свой параметр - person Manjoor; 13.07.2010
comment
Я буквально понятия не имею, я неделю занимаюсь Java, просто пытаясь помочь. Я просто пытаюсь сделать это как можно скорее - person Sam Hank; 13.07.2010

Если я правильно вас понял, вы ищете скользящую среднюю, которая рассчитывается на основе потока данных. Следующий класс, который я написал, предоставляет некоторую такую ​​статистику.

  • скользящая средняя
  • среднее затухание (отражает среднее значение нескольких последних выборок на основе коэффициента затухания).
  • скользящая дисперсия
  • затухающая дисперсия
  • мин и макс.

Надеюсь, поможет.

/**
 * 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;
    }
}
person Omry Yadan    schedule 13.07.2010
comment
Привет, спасибо за ваш вклад, он очень полезен и может помочь мне научиться программировать скользящие средние. Однако я после среднего AT в определенное время. Не скользящая средняя. Но еще раз спасибо, это, вероятно, поможет мне в моей следующей задаче! - person Sam Hank; 13.07.2010
comment
ну, среднее в определенное время — это значение, возвращаемое getAverage() после того, как вы вставили все значения до этого времени. - person Omry Yadan; 13.07.2010

Я думаю, что понял. Вы хотите

  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

Ваша проблема не проста, как показывают случаи, на которые я указал.

person Sanjay Manohar    schedule 14.07.2010
comment
Спасибо за помощь. Я не знаю, что такое синтаксический анализ, но я уверен, что смогу его узнать. тогда это довольно сложно? Я имею в виду, что после недели кодирования я смогу это сделать? - person Sam Hank; 14.07.2010
comment
Кроме того, что вы подразумеваете под самой высокой отметкой времени, которая меньше t? Мои отклонения будут принимать значения от 1 до 10, при этом окончательная дисперсия на уровне 10 будет продолжаться от одной секунды до 11. Таким образом, для средней дисперсии в момент времени t = 3 я бы взял все отклонения в момент времени t = 3 за все дни. , и если нет указанного значения в момент времени t=3, то это означает, что он принимает дисперсию предыдущего доступного времени как свою собственную дисперсию. - person Sam Hank; 14.07.2010
comment
да. «Временная метка» каждой точки данных — это первый столбец ваших данных. Таким образом, «наивысшая отметка времени в тот день, которая меньше t», — это более удобный для компьютера способ записать то, что вы только что сказали. Разбор в вашем случае — это преобразование текста в таблицы чисел. Задача не сложна, если вы будете следовать шагам, которые я сказал, но вам нужно учитывать ловушки, например, когда последний записанный момент времени сам по себе был средним из нескольких точек данных. Я имею в виду, если вы уменьшите мой код, вы можете получить его до 10 строк кода! - person Sanjay Manohar; 15.07.2010
comment
Привет, Санджай, что ты думаешь о коде, который я написал? Очень медленно, но работает... - person Sam Hank; 15.07.2010

Хорошо, у меня есть код, который работает. Но это занимает очень много времени (около 7 месяцев в день, с 30 000 отклонений в день), потому что приходится повторяться очень много раз. Есть ли другие лучшие предложения?

Я имею в виду, что этот код для чего-то, казалось бы, простого, займет около 24-28 часов...

пакет VarPackage;

импортировать java.io.BufferedReader; импортировать java.io.FileReader; импортировать 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;

импортировать 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;

для (Строка строки: 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;

   }

}

вернуть н;

}

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;

для (строка 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;

   }

}

вернуть средние данные;

}

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;
}

}

person Sam Hank    schedule 14.07.2010
comment
Проблема возникает в цикле for, где он выполняет 86400 итераций за каждую секунду в течение дня. Я не знаю, может массив массива массива? Кодирование в порядке и дает мне правильный ответ, как я уже сказал, но оно не дает мне правильный ответ быстро. Так что я делаю это медленнее - person Sam Hank; 15.07.2010