Skip to content

Instantly share code, notes, and snippets.

@TomMarius
Created August 9, 2023 08:18
Show Gist options
  • Select an option

  • Save TomMarius/8b198069ebe492951a29f3d5ba76f60d to your computer and use it in GitHub Desktop.

Select an option

Save TomMarius/8b198069ebe492951a29f3d5ba76f60d to your computer and use it in GitHub Desktop.
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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment