Skip to content

Commit 6ff9911

Browse files
committed
Added linear regression model
1 parent e4df69e commit 6ff9911

File tree

3 files changed

+211
-0
lines changed

3 files changed

+211
-0
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,19 @@ komentojonolla `esipesu.sh`.
2020

2121
Keräile rekisteröintitiedot vuosilta 2016-2021 Python-ohjelmalla
2222
`ev_counts.py`.
23+
24+
### Datan pilkkominen vuosimääristä kuukausimääriksi
25+
26+
Ennustemallia varten vuosittaiset sähköautojen rekisteröintimäärät
27+
on pilkottu kuukausittaisiksi Python-ohjelmassa `ev_counts_monthly.py`.
28+
29+
### Ennustemalli käyttäen lineaarista regressiota
30+
31+
Sähköautojen ensirekisteröintimäärät loppuvuodelle 2022 ja koko
32+
vuodelle 2023 on ennustettu lineaarisen regressiomallin avulla,
33+
käyttäen Scikit-learn-kirjastoa. Tämä versio on tiedostossa
34+
`ev_counts_regression.py`.
35+
36+
Tuloksia voi verrata esimerkiksi Tilastokeskuksen tiedotteeseen
37+
[Tammikuussa 2023 ensirekisteröitiin 7 175 uutta henkilöautoa](https://www.stat.fi/julkaisu/cl8cq3s51778x09w2jlxa1tyh).
38+

ev_counts_monthly.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import csv
2+
3+
filename = 'henkiloautot-sahko-merkit.csv'
4+
5+
all_rows = []
6+
7+
csv_file = open(filename, encoding='iso-8859-1')
8+
reader = csv.reader(csv_file)
9+
headers = next(reader)
10+
for row in reader:
11+
if row[0] in ['M1', 'M1G']:
12+
all_rows.append(row)
13+
csv_file.close()
14+
15+
print(len(all_rows))
16+
17+
years = range(2016, 2023)
18+
counts = {}
19+
for row in all_rows:
20+
if row[1] == '': # ohita tyhjä rek. pvm
21+
continue
22+
year = int(row[1][:4]) # irrota rek. vuosi
23+
if year < years.start: # ohita liian vanha
24+
continue
25+
if year not in counts: # tee uusi lista vuodelle
26+
counts[year] = [0] * 12
27+
month = int(row[1][5:7]) - 1 # irrota rek. kuukausi
28+
counts[year][month] += 1
29+
30+
print(f'Sähköautojen ensirekisteröinnit {years.start} - {years.stop - 1}')
31+
for year in years:
32+
print(f'{year}: {sum(counts[year]):>5}')
33+
for month in range(12):
34+
print(f'\t{month+1:>2}: {counts[year][month]}')
35+
print(f'Yhteensä: {len(all_rows)}')
36+
37+
import matplotlib.pyplot as plt
38+
39+
labels = []
40+
values = []
41+
for year in years:
42+
for month in range(12):
43+
labels.append(f'{year}\n-{month+1}')
44+
values.append(counts[year][month])
45+
46+
plt.bar(labels, values, tick_label=labels)
47+
plt.show()

ev_counts_regression.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import csv
2+
3+
filename = 'henkiloautot-sahko-merkit.csv'
4+
5+
all_rows = []
6+
7+
csv_file = open(filename, encoding='iso-8859-1')
8+
reader = csv.reader(csv_file)
9+
headers = next(reader)
10+
for row in reader:
11+
if row[0] in ['M1', 'M1G']:
12+
all_rows.append(row)
13+
csv_file.close()
14+
15+
print(len(all_rows))
16+
17+
years = range(2016, 2024) # nyt on 2023 mukana
18+
counts = {}
19+
for row in all_rows:
20+
if row[1] == '':
21+
continue
22+
year = int(row[1][:4])
23+
if year < years.start:
24+
continue
25+
if year not in counts:
26+
counts[year] = [0] * 12
27+
month = int(row[1][5:7]) - 1
28+
counts[year][month] += 1
29+
30+
# Lisää tyhjä lista myös vuodelle 2023:
31+
counts[years.stop - 1] = [0] * 12
32+
33+
print(f'Sähköautojen ensirekisteröinnit {years.start} - {years.stop - 1}')
34+
for year in years:
35+
print(f'{year}: {sum(counts[year]):>5}')
36+
for month in range(12):
37+
print(f'\t{month+1:>2}: {counts[year][month]}')
38+
print(f'Yhteensä: {len(all_rows)}')
39+
40+
# Regressiomallia varten muista ensin aktivoida
41+
# virtuaaliympäristö, sitten asenna Scikit-Learn:
42+
# `pip install scikit-learn`
43+
# Matplotlibin asennus on jo vetänyt mukaan NumPy-kirjaston.
44+
45+
import numpy as np
46+
from sklearn.linear_model import LinearRegression
47+
48+
x_arr = []
49+
x_val = 0
50+
y_arr = []
51+
leftover_count = 0 # montako kuukautta on vailla dataa
52+
for year in years:
53+
# Data puuttuu viimeiseltä vuodelta.
54+
# Se täydennetään ennusteen tuottamalla datalla.
55+
if year == 2023:
56+
leftover_count += 12
57+
continue
58+
for month in range(12):
59+
# Data puuttuu myös v. 2022 lopulta
60+
if year == 2022 and month >= 6:
61+
leftover_count += 1
62+
continue
63+
x_arr.append(x_val)
64+
x_val += 1
65+
y_arr.append(counts[year][month])
66+
67+
# Nyt x_arr sisältää arvot 0...77, missä 0 = tammikuu 2016,
68+
# 1 = helmikuu 2016 jne., ja 77 = kesäkuu 2022.
69+
# Yhteensä siis 6 * 12 + 6 = 78 kuukautta.
70+
71+
# y_arr sisältää rekisteröintimäärät 1/2016 ... 6/2022.
72+
#print(len(y_arr))
73+
#print(y_arr)
74+
75+
# NumPy-taulukot ovat hieman erilaisia kuin Pythonin listat,
76+
# joten täytyy tehdä pieni muunnos:
77+
x = np.array(x_arr).reshape((-1, 1))
78+
y = np.array(y_arr)
79+
80+
#print(x)
81+
#print(y)
82+
83+
# Seuraava perustuu artikkeliin
84+
# https://realpython.com/linear-regression-in-python/
85+
86+
# Tehdään lineaarinen regressiomalli ja sovitetaan siihen x ja y:
87+
model = LinearRegression()
88+
model.fit(x, y)
89+
90+
r_sq = model.score(x, y)
91+
print(f"coefficient of determination: {r_sq}")
92+
print(f"intercept: {model.intercept_}")
93+
print(f"slope: {model.coef_}")
94+
95+
# Ennustetaan x:n perusteella y:n arvot
96+
y_pred = model.predict(x)
97+
#print(f"predicted response:\n{y_pred}")
98+
99+
print(f'Ennustetaan {leftover_count} kuukautta...')
100+
future_x = list(range(x_val, x_val + leftover_count))
101+
x_new = np.array(future_x).reshape((-1, 1))
102+
#print(x_new)
103+
y_new = model.predict(x_new)
104+
print(y_new)
105+
print(type(y_new))
106+
107+
# Keräillään valmiit arvot ja niiden otsakkeet kuviota varten
108+
labels = []
109+
year = years.start
110+
month = 0
111+
values = y_arr
112+
for x in x_arr:
113+
labels.append(f'{year}-{month+1:>02}')
114+
month += 1
115+
if month == 12:
116+
month = 0
117+
year += 1
118+
119+
total_count = 0
120+
count_2022 = 0
121+
count_2023 = 0
122+
year = 2022
123+
month = 6
124+
#print(future_x)
125+
for fx in future_x:
126+
count = int(y_new[fx - len(x_arr)])
127+
total_count += count
128+
label = f'{year}-{month+1:>02}'
129+
labels.append(label)
130+
values.append(count) # lisätään ennustettu arvo
131+
print(f'{label}: {count} *')
132+
if year == 2022:
133+
count_2022 += count
134+
if year == 2023:
135+
count_2023 += count
136+
month += 1
137+
if month == 12:
138+
month = 0
139+
year += 1
140+
print(f'Ennuste ajalle 2022-07 - 2023-12: {total_count}')
141+
print(f'Ennuste loppuvuodelle 2022: {count_2022}')
142+
print(f'Ennuste vuodelle 2023: {count_2023}')
143+
144+
import matplotlib.pyplot as plt
145+
print(labels)
146+
print(values)
147+
plt.bar(labels, values, tick_label=labels)
148+
plt.show()

0 commit comments

Comments
 (0)