package main import ( "log" "net/http" "sort" "strconv" "github.com/360EntSecGroup-Skylar/excelize/v2" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/plotutil" "gonum.org/v1/plot/vg" ) func main() { // Step 1: Download the Excel file. resp, err := http.Get("http://portal.chmi.cz/files/portal/docs/meteo/ok/files/PKLM_pro_portal.xlsx") if err != nil { log.Fatal(err) } defer resp.Body.Close() // Step 2: Read the Excel file. f, err := excelize.OpenReader(resp.Body) if err != nil { log.Fatal(err) } // Assuming data starts from 3rd row, and columns are 'A' for year and 'B' for TMI. rows, err := f.GetRows("Sheet1") if err != nil { log.Fatal(err) } yearlyData := make(map[int]float64) var total float64 count := 0 for _, row := range rows[2:] { year, err := strconv.Atoi(row[0]) if err != nil { continue } if year < 1889 { continue } tmi, err := strconv.ParseFloat(row[1], 64) if err != nil { continue } yearlyData[year] = tmi total += tmi count++ } avg := total / float64(count) rollingAvgData := rollingAverage(yearlyData, 10) ptsRolling := make(plotter.XYs, len(rollingAvgData)) i = 0 for year, tmi := range rollingAvgData { ptsRolling[i].X = float64(year) ptsRolling[i].Y = tmi - avg i++ } err = plotutil.AddLinePoints(p, "Rolling Change", ptsRolling) if err != nil { log.Fatal(err) } // Plotting. p, err := plot.New() if err != nil { log.Fatal(err) } p.Title.Text = "Change in daily temperatures in Prague, Czechia since 1900" p.X.Label.Text = "Year" p.Y.Label.Text = "Change in temperature [°C]" pts := make(plotter.XYs, count) i := 0 for year, tmi := range yearlyData { pts[i].X = float64(year) pts[i].Y = tmi - avg i++ } err = plotutil.AddLinePoints(p, "Change", pts) if err != nil { log.Fatal(err) } if err := p.Save(12*vg.Inch, 8*vg.Inch, "output.png"); err != nil { log.Fatal(err) } } func rollingAverage(data map[int]float64, window int) map[int]float64 { sortedYears := make([]int, 0, len(data)) for year := range data { sortedYears = append(sortedYears, year) } sort.Ints(sortedYears) result := make(map[int]float64) halfWindow := window / 2 for i, year := range sortedYears { start := i - halfWindow if start < 0 { start = 0 } end := i + halfWindow if end >= len(sortedYears) { end = len(sortedYears) - 1 } sum := 0.0 count := 0 for j := start; j <= end; j++ { sum += data[sortedYears[j]] count++ } result[year] = sum / float64(count) } return result }