Szilard Csedo Ответов: 1

Как я могу рассчитать ежедневные средние/минимальные/максимальные значения годовых данных


У меня есть файл .CSV, содержащий данные о погоде за весь год, я хотел бы рассчитать значения, необходимые для каждого дня, и распечатать их в другой файл .CSV .
Файл .csv выглядит следующим образом :

stationid	datestamp	wgust	wspeedavg	wdir	wsector	alarmamber	alarmred			
FX32	31-12-19 23:52	20	0	155				0	0	0
FX32	31-12-19 23:50	18.99	0	159				0	0	0
FX32	31-12-19 23:48	18.01	0	154				0	0	0
FX32	31-12-19 23:42	18.99	0	152				0	0	0
FX32	31-12-19 23:40	18.99	0	151				0	0	0
FX32	30-12-19 23:30	18.99	0	144				0	0	0
FX32	30-12-19 23:28	18.99	0	147				0	0	0
FX32	30-12-19 23:22	20	0	135				0	0	0


Что я уже пробовал:

Я пробовал этот код до сих пор , он может читать файл и вычислять общее среднее значение/мин/макс. Есть ли способ, который я могу указать, чтобы делать это изо дня в день ?

package sortdata;


import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;

import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;

import com.opencsv.exceptions.CsvDataTypeMismatchException;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;

import java.io.BufferedReader;

import java.io.FileWriter;
import java.io.IOException;


import java.io.Writer;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ArrayList;




import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.List;


import java.util.LongSummaryStatistics;
import java.util.Scanner;

import javax.xml.crypto.Data;

import org.apache.commons.collections.iterators.ObjectArrayListIterator;


public class Main {


    /**
     * @param args
     *
     */
    @SuppressWarnings({ "rawtypes", "unchecked", "oracle.jdeveloper.java.nested-assignment" })
    public static void main(String[] args) throws IOException, CsvDataTypeMismatchException,
                                                  CsvRequiredFieldEmptyException {
        

        String fileName = "C:\\JDeveloper\\wdata.csv";
        Path myPath = Paths.get(fileName);
        
        ArrayList<String>  d = new ArrayList<String>();
          convertDegreeToCardinalDirection direction = new convertDegreeToCardinalDirection();

        try (BufferedReader br = Files.newBufferedReader(myPath, StandardCharsets.UTF_8)) {    
           


            

            HeaderColumnNameMappingStrategy<Read> strategy = new HeaderColumnNameMappingStrategy<>();
            strategy.setType(Read.class);
            


            CsvToBean toBean = new CsvToBeanBuilder(br).withType(Read.class)
                                                       .withMappingStrategy(strategy)
                                                       .withIgnoreLeadingWhiteSpace(true)
                                                       .build();


            List<Read> Data = toBean.parse();                                                  
                                              
          //Calc for AVG MIN MAX WSpead

            final DoubleSummaryStatistics Wind = Data.stream()
                                                     .mapToDouble(Read::getWgust)
                                                     .summaryStatistics();

            final double averageWind = Wind.getAverage();
            final double Windmin = Wind.getMin();
            final double Windmax = Wind.getMax();
            final int Windtotal = (int) Wind.getCount();

            //calc for AVG MIN MAX Wdir

            final IntSummaryStatistics WindDIR = Data.stream()
                                                     .mapToInt(Read::getWdir)
                                                     .summaryStatistics();

            final double averageWdir = WindDIR.getAverage();
            final int maxWdir = WindDIR.getMax();
            final int minWdir = WindDIR.getMin();
           
            


            System.out.println("Total Number of Values : " + Windtotal);
            System.out.println("AverageWindSpeed: " + averageWind);
            System.out.println("Minimum WIndSpeed: " + Windmin);
            System.out.println("Maximum WIndSpeed: " + Windmax);

            System.out.println("AverageWindDir: " + averageWdir);
            System.out.println("Minimum WIndDir: " + minWdir);
            System.out.println("Maximum WIndDir: " + maxWdir);
            // System.out.println(stat);

            
                               Writer writer = new FileWriter("Datasorter1.csv");
                               StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer).build();
                               beanToCsv.write(Wind);
                               writer.close();
                    } //end of buffer reader
    } //end if main string  

}// end of class

Также есть класс Read который содержит следующее :
public class Read {
    @CsvBindByName(column = "stationid", required = true)
    private String stationid;
    @CsvBindByName(column = "datestamp", required = true)
    @CsvDate("dd-MM-yy HH:mm")
    private Date datestamp;
    @CsvBindByName(column = "wgust", required = true)
    private double wgust;
    @CsvBindByName(column = "wdir", required = true)
    private int wdir;
    
    
    private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);


      
    

    public void setStationid(String stationid) {
        String oldStationid = this.stationid;
        this.stationid = stationid;
        _propertyChangeSupport.firePropertyChange("stationid", oldStationid, stationid);
    }

    public String getStationid() {
        return stationid;
    }

    public void setDatestamp(Date datestamp) {
        Date oldDatestamp = this.datestamp;
        this.datestamp = datestamp;
        _propertyChangeSupport.firePropertyChange("datestamp", oldDatestamp, datestamp);
    }

    public Date getDatestamp() {
        return datestamp;
    }

    public void setWgust(double wgust) {
        double oldWgust = this.wgust;
        this.wgust = wgust;
        _propertyChangeSupport.firePropertyChange("wgust", oldWgust, wgust);
    }

    public double getWgust() {
        return wgust;
    }

    public void setWdir(int wdir) {
        int oldWdir = this.wdir;
        this.wdir = wdir;
        _propertyChangeSupport.firePropertyChange("wdir", oldWdir, wdir);
    }

    public int getWdir() {
        return wdir;
    }


    public void addPropertyChangeListener(PropertyChangeListener l) {
        _propertyChangeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        _propertyChangeSupport.removePropertyChangeListener(l);
    }
 
    @Override
    public String toString() {

        StringBuilder builder = new StringBuilder();
        builder.append("Station{id=")
               .append(stationid)
               .append(", Date=")
               .append(datestamp)
               .append(", Wspeed=")
               .append(wgust)
               .append(", Direction=")
               .append(wdir)
               .append("}");

        return builder.toString();
    }


Я был бы признателен за любую помощь (пример кода, если это возможно), у меня нет большого опыта в кодировании, и это было бы на работе.

Richard MacCutchan

Вам просто нужно добавить тест выбора, чтобы читать принимать только те записи, которые имеют правильную дату. Аналогичным образом можно выбрать записи, имеющие один и тот же месяц.

OriginalGriff

Я предполагаю, что он скопировал код и понятия не имеет, как он работает, а тем более как его модифицировать ... :вздыхать:

Szilard Csedo

К сожалению, я начал java 3 дня назад, и у меня есть немного опыта из школы о c++, так что у меня есть нулевой опыт, но до сих пор мне удалось собрать это вместе из уроков, учебников, примеров кодов, даже пришлось научиться использовать API (большинство издателей рекомендовали OPENCSV) я узнал много , но есть гораздо больше, и каждый предмет связан, что делает его действительно трудным для меня :) . Я был бы признателен, если бы вы указали мне правильное направление. Спасибо

Maciej Los

Имя класса немного сбивает с толку, потому что [Read] скорее используется для определения метода.

Szilard Csedo

Спасибо за разъяснение, переименовали его в ReadW.

1 Ответов

Рейтинг:
2

Maciej Los

Насколько я вижу, вы в состоянии получить summaryStatistics для всего списка:

List<Read> Data = toBean.parse();  
//skipped lines
inal DoubleSummaryStatistics Wind = Data.stream()
                               .mapToDouble(Read::getWgust)
                               .summaryStatistics();


Все, что вам нужно сделать, это получить определенную часть данных (месяц, квартал, год) в другой список, а затем позвонить summaryStatistics() метод для этого меньшего списка.


Szilard Csedo

Пожалуйста ,поправьте меня, если я ошибаюсь, но таким образом я смогу сделать только среднемесячное значение, если я скопирую только день и соответствующую информацию, как я могу указать, когда начнется следующий день ?

Maciej Los

Как я уже упоминал, вам нужно определить метод, который будет получать "полный список" и возвращать список данных, содержащих ежемесячные, квартальные или годовые данные.
Если вы хотите определить универсальный метод, то вам нужно передать в него 2 даты. Первый - определяет начало диапазона дат, второй - определяет конец диапазона дат. Подумайте об этом и начните кодировать.
[Редактировать]
Если вы хотите получать ежедневные данные, вам нужно вызвать метод, чтобы получить меньший список внутри цикла. Итак, получите mininimum и максимальную дату csv-данных, а затем запустите цикл.

Szilard Csedo

Я получаю входную строку из консоли с соответствующей "датой" в следующем формате ("dd-MM-yy"), а затем преобразую ее в дату с помощью simpleDateFormat.
в моем методе я получаю эту дату и использую ее для сравнения с моим столбцом "datestamp" из файла .csv. Но мой файл содержит дату в следующем формате ("dd-MM-yy HH:mm"), и я считаю, что именно эта проблема вызывает у меня проблемы с сравнениями .
Скрыть   скопировать код

if (date.equals(val))...

Где дата - это из записей, а val-из консольного ввода .
Можете ли вы предложить решение, как игнорировать нерелевантные поля ?

Maciej Los

Похоже, вы говорите о сравнении строк вместо дат. Преобразуйте обе даты (исходящие из консоли и csv) в правильный тип данных datetime.

string consoledate = "30-03-20";
string csvdate = "30-03-20 20:49";

System.Globalization.CultureInfo ci = System.Globalization.CultureInfo.InvariantCulture;
DateTime dt1 = DateTime.ParseExact(consoledate, "dd-MM-yy", ci);
DateTime dt2 = DateTime.ParseExact(csvdate, "dd-MM-yy HH:mm", ci);
dt2 = dt2.AddHours(-dt2.Hour).AddMinutes(-dt2.Minute).AddSeconds(-dt2.Second);

var result = dt1.Equals(dt2);

Szilard Csedo

Извините , что причиняю вам боль, но как я могу реализовать это на Java ? DateTime-это java-пакет, но я не смог найти его для "CultureInfo" .

Maciej Los

Извините, я забыл, что вам нужно Java-решение.
Я предоставил пример в c#, потому что у меня нет инструмента разработчика Java, установленного в моей системе. Java-эквивалент CultureInfo в C# - это Локаль (Java Platform SE 8 )[^]