Statistiche sulla partecipazione al Bebras italiano 2024/25

In [1]:
from IPython.display import HTML, Markdown

HTML('''<script>
code_show=true; 
function code_toggle() {
 if (code_show){
 $('div.input').hide();
 } else {
 $('div.input').show();
 }
 code_show = !code_show
} 
$( document ).ready(code_toggle);
</script>
<input type="button" value="Clicca per vedere/nascondere il codice Python" onclick="code_toggle()">''')
Out[1]:
In [2]:
import warnings
warnings.filterwarnings('once')
#warnings.filterwarnings('ignore')
In [3]:
%matplotlib inline
import pandas as pd
import urllib.request
from IPython.display import display, Markdown
import matplotlib.pyplot as plt

pd.options.display.max_rows = None
plt.style.use('ggplot')
In [4]:
miur = pd.read_csv('bebras_school_list.zip', low_memory=False)

def norm_region(r):
    """Normalize the name of a region. It also corrects wrong names."""
    r = r.strip().upper()
    if r == 'FVG' or r.startswith('FRIULI'):
        return 'FRIULI-VENEZIA GIULIA'
    if r.startswith('EMILIA') or 'ROMAGNA' in r:
        return 'EMILIA-ROMAGNA'
    if r.startswith('TRENTINO') or r.startswith('ALTO ADIGE') or r == 'P.A.T.' or 'TRENTO' in r:
        return 'TRENTINO ALTO ADIGE / SÜDTIROL'
    if r.startswith('LO'):
        return 'LOMBARDIA'
    if r.endswith('MONTE'):
        return 'PIEMONTE'
    if r.startswith('VALLE') or 'AOSTA' in r:
        return "VALLE D'AOSTA / VALLÉE D'AOSTE"
    if r == 'G6GG6Y' or r == 'ITALIA':
        return None
    if r == 'ALBANIA' or r == 'BAVIERA' or r == 'SIERRA' or r == 'DDDD' \
       or r == 'FRANCE' or r == 'SVIZZERA' or r == 'CROAZIA' or r == 'ILFOV' \
       or 'ISTRIA' in r or 'SHUBRA' in r:
        return 'ESTERO'
    else:
        return r

def infer_school_type(k):
    knorm = k['school_kind'].strip().upper()
    cnorm = k['school_code'].strip().upper()
    if cnorm and miur[miur['i_code'] == cnorm]['i_type'].count() > 0:
        knorm = str(miur[miur['i_code'] == cnorm]['i_type'].iloc[0])
    if 'PRIMARIA' in knorm or 'INFANZIA' in knorm or 'ELEMENTARE' in knorm:
        return 'E'
    if 'PRIMO GRADO' in knorm or ('MEDIA' in knorm and (not 'SUP' in knorm))\
    or '1°' in knorm or ' I GRADO' in knorm or knorm == 'IC':
        return 'M'
    if 'COMPRENSIVO' in knorm:
        return 'EM'
    if 'SECONDO GRADO' in knorm or '2°' in knorm  or 'II GRADO' in knorm \
    or 'LICEO' in knorm or 'ITI' in knorm or 'PROF' in knorm or 'IST TEC' in knorm \
    or 'TECNICO' in knorm or 'MAGISTRALE' in knorm or 'SUPERIORE' in knorm:
        return 'S'
    if knorm == 'STATALE' or 'C.D.38':
        return 'EMS'
    else:
        return knorm

Insegnanti, stima delle squadre e alunni

In [5]:
from datetime import date
In [6]:
YEAR=2024
LAST_DAY=date(YEAR,11,10)

with open('secret.key') as k:
    key = k.readline().strip()

r = urllib.request.urlopen(("https://bebras.it/api?key={}&view=teachers_edition"+
                           "&edition=bebras_{}&subscription=1").format(key, YEAR))

with open("teachers.json", "w") as tw:
     tw.writelines(r.read().decode('utf-8'))        

teachers = pd.DataFrame(pd.read_json("teachers.json", convert_axes=True))

teachers.index = range(len(teachers))
teachers['confirm_time'] = pd.to_datetime(teachers['confirm_time'], unit='s')
teachers['enter_time'] = pd.to_datetime(teachers['enter_time'], unit='s')

teachers['school_code'] = teachers['school_code'].str.strip().str.upper()
teachers['school_type'] = teachers[['school_kind','school_code']].apply(infer_school_type, axis=1)
filled = len(teachers)
regteams = teachers['teams_active'].sum()

today = date.today()
if today > LAST_DAY:
    today = LAST_DAY
s = """*{}:* **{:d}** insegnanti hanno confermato la partecipazione; 
ci sono **{:d}** squadre già registrate (~*{:d}* alunni).
"""
display(Markdown(s.format(str(today)[:19], 
                          filled, regteams, 3*regteams)))

if today <= LAST_DAY:
    isotoday = today.isoformat()[:10]
    with open("stats-" + isotoday + ".txt", "w") as stat:
        stat.write(f"{filled:d} {regteams:d} {3*regteams:d}\n")

2024-11-10: 1261 insegnanti hanno confermato la partecipazione; ci sono 28811 squadre già registrate (~86433 alunni).

In [7]:
oldeditions = (2015, 2016, 2017, "bebras_2018", "bebras_2019", "bebras_2020", "bebras_2021", "bebras_2022", "bebras_2023")
In [8]:
oldteachers = {}
for y in oldeditions:
    r = urllib.request.urlopen(("https://bebras.it/api?key={}&view=teachers_edition"+
                                "&edition={}").format(key, y))
    with open("teachers{}.json".format(y), "w") as tw:
        tw.writelines(r.read().decode('utf-8'))

    oldteachers[y] = pd.DataFrame(pd.read_json("teachers{}.json".format(y), convert_axes=True))[3:]
    #oldtteachers[y]['school_type'] = oldteachers[['school_kind','school_code']].apply(infer_school_type, axis=1)
In [9]:
intersect = {}
for y in oldeditions:
    intersect[y] = pd.merge(teachers, oldteachers[y], on='id', how='inner')
    intersect[y]['deltateams'] = intersect[y]['teams_active_x'] - intersect[y]['teams_active_y']
    returning = intersect[y]['id'].count()
    base = len(oldteachers[y][oldteachers[y]['teams_active'] > 0])
    s = """*{:d}* insegnanti hanno già partecipato all'edizione {} (**{:.0f}%** dei partecipanti di quell'edizione), 
il numero di squadre è aumentato in media di {:.1f} (deviazione standard {:.0f}).
"""
    display(Markdown(s.format(returning, str(y)[-4:], 
                              100*float(returning)/float(base),
                              intersect[y]['deltateams'].mean(), intersect[y]['deltateams'].std() 
                             )))

44 insegnanti hanno già partecipato all'edizione 2015 (18% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 10.5 (deviazione standard 26).

87 insegnanti hanno già partecipato all'edizione 2016 (12% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 15.6 (deviazione standard 46).

165 insegnanti hanno già partecipato all'edizione 2017 (16% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 14.6 (deviazione standard 43).

245 insegnanti hanno già partecipato all'edizione 2018 (21% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 13.0 (deviazione standard 39).

294 insegnanti hanno già partecipato all'edizione 2019 (32% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 10.1 (deviazione standard 35).

266 insegnanti hanno già partecipato all'edizione 2020 (53% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -24.3 (deviazione standard 79).

393 insegnanti hanno già partecipato all'edizione 2021 (50% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -16.9 (deviazione standard 49).

517 insegnanti hanno già partecipato all'edizione 2022 (53% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -1.2 (deviazione standard 30).

744 insegnanti hanno già partecipato all'edizione 2023 (63% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 0.5 (deviazione standard 23).

In [10]:
all_intersect = pd.merge(teachers['id'], oldteachers[oldeditions[0]]['id'], on='id', how='inner')

for e in oldeditions[1:]:
    all_intersect = pd.merge(all_intersect['id'], oldteachers[e]['id'], on='id', how='inner')

    
print(f"Hanno partecipato a tutte le {len(oldeditions) + 1} edizioni: {len(all_intersect)} insegnanti.")

all_editions = pd.merge(teachers, all_intersect, on='id', how='inner')
#display(all_editions[['firstname', 'name', 'school_name', 'school_city', 'school_kind']])
Hanno partecipato a tutte le 10 edizioni: 24 insegnanti.
In [11]:
institutes = teachers[(teachers['school_code'].str.strip() != "") 
                      & (teachers['subscription'] > 0) 
                      & (teachers['confirm_time'].dt.date > date(YEAR,9,1))].groupby('school_code')['id'].count()

print("Totale istituti con codice meccanografico: {}; numero medio insegnanti per codice: {:.2f}".format(len(institutes), institutes.mean()))
Totale istituti con codice meccanografico: 516; numero medio insegnanti per codice: 1.98
In [12]:
import os
data = []
for path, dirs, files in os.walk("."):
    for f in files:
        if path == '.' and f.startswith("stats-"):
            d = [int(x) for x in f.split('.')[0].split('-')[1:4]]
            with open(f,"r") as df:
                nn = [int(x) for x in df.readline().strip().split(" ")]
                dd = LAST_DAY - date.fromtimestamp(os.stat(f).st_mtime)
                data.append((dd, nn))
data = pd.DataFrame.from_dict(dict(data), orient="index", 
                               columns=["insegnanti","squadre","alunni"]).sort_index(ascending=False)
data['giorni'] = (data.index * -1).days
In [13]:
olddata = []
for path, dirs, files in os.walk("old"):
    for f in files:
        if f.startswith("stats-"):
            d = [int(x) for x in f.split('.')[0].split('-')[1:4]]
            with open(path + "/" + f,"r") as df:
                nn = [int(x) for x in df.readline().strip().split(" ")]
                olddata.append((date(YEAR-1,11,13) - date(*d), nn))
olddata = pd.DataFrame.from_dict(dict(olddata), orient="index", 
                                  columns=["insegnanti","squadre","alunni"]).sort_index(ascending=False)
olddata['giorni'] = (olddata.index * -1).days
In [14]:
fig, ax = plt.subplots(1,2)
fig.set_size_inches(11,5)

for i, t in enumerate(['squadre', 'insegnanti']):
    ax[i].plot([-d.days for d in data.index], list(data[t]), label=t + ' ' + str(YEAR))
    ax[i].plot([-d.days for d in olddata.index], list(olddata[t]), '--', label=t + ' ' + str(YEAR-1) )
    ax[i].legend()
    ax[i].set_xlim([-50,7])
    delta = (data[t].max()-olddata[t].max())/olddata[t].max()
    _ = ax[i].text(-.9*data[t].count(), .75*data[t].max(), '{:+.1f}%'.format(delta*100), color='red' if delta < 0 else 'green')
No description has been provided for this image
In [15]:
r = urllib.request.urlopen(("https://bebras.it/api?key={}&view=teams"+
                           "&edition=bebras_{}").format(key, YEAR))
with open("teams.json", "w") as tw:
     tw.writelines(r.read().decode('utf-8'))        
In [16]:
import json
In [17]:
CATS = ('kilo','mega','giga','tera','peta')
CATEGORIES = tuple(f'{c}' for c in CATS)
In [18]:
with open("teams.json") as t:
    teams = pd.DataFrame(json.load(t)['teams'])

oldteams = pd.DataFrame({'class': CATS,f'teams_{YEAR-1}':[3627,10223,4663,2760,1894]})
oldteams.index = oldteams['class']
del oldteams['class']
teams['macro'] = teams['class'].str.slice(0,4)
tdata = teams.groupby('macro').count()['login'].copy()
In [19]:
tdata = pd.concat([tdata, oldteams],axis=1)
tdata = tdata.reindex(index = CATEGORIES)
In [20]:
tdata['Incremento potenziale %'] = 100*(tdata['login']-tdata[f'teams_{YEAR-1}'])/tdata[f'teams_{YEAR-1}']
display(tdata)

print(f"""In totale {tdata['login'].sum()} squadre iscritte 
({100*(tdata['login'].sum()-olddata['squadre'].max())/olddata['squadre'].max():+.2f}% rispetto alle squadre iscritte nel {YEAR-1})
({100*(tdata['login'].sum()-oldteams['teams_2023'].sum())/oldteams['teams_2023'].sum():+.2f}% rispetto alle squadre partecipanti nel {YEAR-1})
""")

students = teams.groupby('class').count().apply(lambda x: 3*x, axis=1)['login']

print('\nIl numero di partecipanti previsto per categoria:')
display(students)
print(f"Il numero totale di partecipanti previsto è {students.sum()}.")
login teams_2023 Incremento potenziale %
kilo 4239 3627 16.873449
mega 12500 10223 22.273305
giga 6100 4663 30.817071
tera 3437 2760 24.528986
peta 2545 1894 34.371700
In totale 28821 squadre iscritte 
(+2.29% rispetto alle squadre iscritte nel 2023)
(+24.41% rispetto alle squadre partecipanti nel 2023)


Il numero di partecipanti previsto per categoria:
class
giga    18300
kilo    12717
mega    37500
peta     7635
tera    10311
Name: login, dtype: int64
Il numero totale di partecipanti previsto è 86463.

La popolazione studentesca nazionale

Dati ISTAT della popolazione studentesca scuola primaria e secondaria nel 2021 (fonte: http://dati.istat.it)

In [21]:
istat = pd.read_csv('studenti_italia.csv', 
                usecols=['Territorio', 
                         'Ordine scolastico', 
                         'Value'])
In [22]:
istat = istat.rename(columns={'Territorio':'regione'})
In [23]:
istat['regione'] = istat['regione'].str.upper()
tot_istat = istat.groupby('regione')['Value'].sum()
reg_istat = istat.groupby(['regione', 'Ordine scolastico'])['Value'].sum()
In [24]:
all_istat = reg_istat.unstack()
all_istat['totale'] = tot_istat

all_istat
Out[24]:
Ordine scolastico primaria secondaria I grado secondaria II grado totale
regione
ABRUZZO 53145 34299 56435 143879
BASILICATA 20922 14333 28202 63457
CALABRIA 80867 52845 95931 229643
CAMPANIA 270047 181821 330549 782417
EMILIA-ROMAGNA 193247 125634 198096 516977
FRIULI-VENEZIA GIULIA 48202 31888 49939 130029
ITALIA 2588383 1706482 2730359 7025224
LAZIO 253371 164187 258650 676208
LIGURIA 56301 38096 62401 156798
LOMBARDIA 448350 293318 409987 1151655
MARCHE 63478 41880 71735 177093
MOLISE 10919 7111 13158 31188
PIEMONTE 177669 117200 177897 472766
PUGLIA 171014 114102 200441 485557
SARDEGNA 60420 40327 71806 172553
SICILIA 219759 145681 239790 605230
TOSCANA 151736 100906 166834 419476
TRENTINO ALTO ADIGE / SÜDTIROL 54030 33924 42514 130468
UMBRIA 36097 23874 38850 98821
VALLE D'AOSTA / VALLÉE D'AOSTE 5445 3633 5566 14644
VENETO 213364 141423 211578 566365

Analisi delle gare

In [25]:
snames = {'E': 'primaria', 'M': 'secondaria I grado', 'S': 'secondaria II grado'}
In [26]:
FIRST=121 # da aggiornare per l'anno corrente

for i, k in enumerate(CATS):
    if not os.path.exists(f"overview-{k}.json"):
        r = urllib.request.urlopen(f"https://bebras.it/api?key={key}&view=exams&test={FIRST+i}&examdata=0&edition=bebras_{YEAR}&events=0")
        with open(f"overview-{k}.json", "w") as tw:
            tw.writelines(r.read().decode('utf-8'))
In [27]:
import json

overview = []
for k in CATEGORIES:
    with open(f"overview-{k}.json", "r") as t:
        j = json.load(t)
        overview += j['exams']
In [28]:
dfov = pd.DataFrame(overview)
In [29]:
gare = pd.DataFrame()
gare['categoria'] = dfov['category'].str.lower().astype(pd.api.types.CategoricalDtype(categories = CATEGORIES, ordered=True))
gare['insegnante'] = dfov['teacher_id'].astype('int64')
gare['login'] = dfov['login']
gare['status'] = dfov['exam_valid_score']
gare['risultato'] = dfov['score']
gare['data'] = pd.to_datetime(dfov['time'])
gare['studenti'] = dfov['team_composition'].map(lambda tt: 0 if type(tt) != type({}) else len([s for s in tt['members'] if s['name'] != '' ]))
In [30]:
fid = teachers.set_index('id')
fid['regione'] = fid['school_region'].map(norm_region)
gare = gare.join(fid[['regione']],on='insegnante')
In [31]:
done = gare[gare['status'] == 1]
In [32]:
f'In tutto, completate {len(done)} gare (~{len(done)*3} studenti)'
Out[32]:
'In tutto, completate 23723 gare (~71169 studenti)'

Insegnanti partecipanti

In [33]:
len(done.groupby(['insegnante']))
Out[33]:
1141

Insegnanti per regione che hanno partecipato

In [34]:
display(done.groupby(['regione'])['insegnante'].nunique())
regione
ABRUZZO                             4
BASILICATA                         17
CALABRIA                            3
CAMPANIA                          114
EMILIA-ROMAGNA                     56
ESTERO                              6
FRIULI-VENEZIA GIULIA              27
LAZIO                              58
LIGURIA                            22
LOMBARDIA                         309
MARCHE                             23
MOLISE                             15
PIEMONTE                           70
PUGLIA                             52
SARDEGNA                           20
SICILIA                            16
TOSCANA                            62
TRENTINO ALTO ADIGE / SÜDTIROL     40
UMBRIA                             13
VALLE D'AOSTA / VALLÉE D'AOSTE     49
VENETO                            164
Name: insegnante, dtype: int64

Insegnanti per categoria

In [35]:
display(done.groupby(['categoria'], observed=True)['insegnante'].nunique())
categoria
kilo    301
mega    645
giga    445
tera    148
peta    109
Name: insegnante, dtype: int64

Squadre per categoria

In [36]:
with pd.option_context('display.float_format', '{:.0f}'.format):
    display(done.groupby(['regione', 'categoria'], observed=True)['login'].count())
regione                         categoria
ABRUZZO                         kilo           43
                                mega           20
                                giga            5
                                peta           49
BASILICATA                      kilo          101
                                mega          236
                                giga          126
CALABRIA                        kilo            1
                                tera           11
CAMPANIA                        kilo          363
                                mega         1002
                                giga          362
                                tera          228
                                peta          181
EMILIA-ROMAGNA                  kilo          124
                                mega          537
                                giga          241
                                tera          177
                                peta           94
ESTERO                          kilo           12
                                mega            3
                                giga            2
                                tera           16
                                peta           63
FRIULI-VENEZIA GIULIA           kilo           73
                                mega           67
                                giga           21
                                tera          348
                                peta          134
LAZIO                           kilo          295
                                mega          296
                                giga          169
                                tera           51
                                peta          170
LIGURIA                         kilo           84
                                mega          158
                                giga           90
                                tera           21
                                peta           98
LOMBARDIA                       kilo          851
                                mega         2895
                                giga         1479
                                tera          889
                                peta          292
MARCHE                          kilo           11
                                mega          371
                                giga           93
                                tera           82
                                peta          137
MOLISE                          kilo           12
                                mega          133
                                giga           63
PIEMONTE                        kilo          115
                                mega          828
                                giga          351
                                tera          194
                                peta          111
PUGLIA                          kilo          243
                                mega          698
                                giga          279
                                tera           86
                                peta           32
SARDEGNA                        kilo           60
                                mega          130
                                giga           64
                                tera           28
                                peta           67
SICILIA                         kilo            9
                                mega           69
                                giga           47
                                tera           19
                                peta           71
TOSCANA                         kilo          184
                                mega          528
                                giga          238
                                tera           64
                                peta            1
TRENTINO ALTO ADIGE / SÜDTIROL  kilo          137
                                mega          553
                                giga          235
                                tera           63
                                peta           29
UMBRIA                          kilo            1
                                mega          234
                                giga          134
                                tera           80
VALLE D'AOSTA / VALLÉE D'AOSTE  kilo          139
                                mega          480
                                giga          283
VENETO                          kilo          612
                                mega         1468
                                giga          729
                                tera          291
                                peta          353
Name: login, dtype: int64

Studenti per categoria

In [37]:
with pd.option_context('display.float_format', '{:.0f}'.format):
    display(done.groupby(['regione', 'categoria'], observed=True)['studenti'].sum())
regione                         categoria
ABRUZZO                         kilo           81
                                mega            0
                                giga            0
                                peta          139
BASILICATA                      kilo          134
                                mega          477
                                giga          256
CALABRIA                        kilo            3
                                tera           33
CAMPANIA                        kilo          764
                                mega         2353
                                giga          812
                                tera          409
                                peta          245
EMILIA-ROMAGNA                  kilo          211
                                mega         1106
                                giga          509
                                tera          343
                                peta          233
ESTERO                          kilo           31
                                mega            8
                                giga            4
                                tera           41
                                peta          189
FRIULI-VENEZIA GIULIA           kilo          153
                                mega           77
                                giga           14
                                tera          737
                                peta          251
LAZIO                           kilo          616
                                mega          656
                                giga          287
                                tera          131
                                peta          410
LIGURIA                         kilo          135
                                mega          310
                                giga          163
                                tera           60
                                peta           91
LOMBARDIA                       kilo         1762
                                mega         5613
                                giga         2919
                                tera         1358
                                peta          637
MARCHE                          kilo           16
                                mega          876
                                giga          258
                                tera          204
                                peta          375
MOLISE                          kilo           26
                                mega          322
                                giga          144
PIEMONTE                        kilo          151
                                mega         1304
                                giga          558
                                tera          405
                                peta          115
PUGLIA                          kilo          673
                                mega         1535
                                giga          702
                                tera          235
                                peta           90
SARDEGNA                        kilo          104
                                mega          329
                                giga          185
                                tera           45
                                peta          112
SICILIA                         kilo           18
                                mega          143
                                giga          106
                                tera           35
                                peta          172
TOSCANA                         kilo          479
                                mega         1187
                                giga          624
                                tera          168
                                peta            2
TRENTINO ALTO ADIGE / SÜDTIROL  kilo          253
                                mega          640
                                giga          260
                                tera          178
                                peta           85
UMBRIA                          kilo            0
                                mega           85
                                giga          122
                                tera          152
VALLE D'AOSTA / VALLÉE D'AOSTE  kilo          252
                                mega          999
                                giga          609
VENETO                          kilo         1296
                                mega         3202
                                giga         1541
                                tera          586
                                peta          658
Name: studenti, dtype: int64

Cartografia ISTAT 2011 (fonte: http://www.istat.it/it/archivio/24613), convertita con il comando:

ogr2ogr -f GeoJSON -s_srs reg2011_g.prj -t_srs EPSG:4326 it.json reg2011_g.shp

(fonte: https://gist.github.com/riccardoscalco/6029355)

In [38]:
import geopandas as gpd
%matplotlib inline

it = gpd.read_file("it.json")

TYPES = ['totale'] + list(snames.values())

dreg = done.groupby(['regione'], observed=True).count()
dregk = done.groupby(['regione','categoria'], observed=True).count()

sreg = done.groupby(['regione'], observed=True).sum(numeric_only=True)
sregk = done.groupby(['regione','categoria'], observed=True).sum(numeric_only=True)


def get_data_with_default(geo, i, t, ddata, sdata, jj, labeld='login', labels='studenti'):
    try:
        geo.loc[i, 'squadre' + ' ' + t] = 0
        for j in jj:
            geo.loc[i, 'squadre' + ' ' + t] += ddata.loc[j, labeld] if ddata.loc[j, labeld] > 0 else 0 
    except:
        geo.loc[i, 'squadre' + ' ' + t] += 0
    try:
        geo.loc[i, 'studenti' + ' ' + t] = 0
        for j in jj:
            geo.loc[i, 'studenti' + ' ' + t] += sdata.loc[j, labels] if sdata.loc[j, labels] > 0 else 0
    except:
        geo.loc[i, 'studenti' + ' ' + t] += 0

        
for i, r in it.iterrows():
    for cname in all_istat.index:
        if r['NOME_REG'][0:5] == cname[0:5]:
            it.loc[i, 'NOME_REG'] = cname
            get_data_with_default(it, i, TYPES[0], dreg, sreg, [cname])
            get_data_with_default(it, i, TYPES[1], dregk, sregk, [(cname, 'kilo')])
            get_data_with_default(it, i, TYPES[2], dregk, sregk, [(cname, 'mega'), (cname, 'giga')])
            get_data_with_default(it, i, TYPES[3], dregk, sregk, [(cname, 'tera'), (cname, 'peta')])
                
            it.loc[i, 'popolazione ' + TYPES[0]] = all_istat.loc[cname, 'totale']
            it.loc[i, 'popolazione ' + TYPES[1]] = all_istat.loc[cname, snames['E']]
            it.loc[i, 'popolazione ' + TYPES[2]] = all_istat.loc[cname, snames['M']]
            it.loc[i, 'popolazione ' + TYPES[3]] = all_istat.loc[cname, snames['S']]
            break

for t in TYPES:
    it['copertura ' + t] = 1000 * it['studenti ' + t] / it['popolazione ' + t]

fig, ax = plt.subplots(2,2)
fig.set_size_inches(15,11)
for i, t in enumerate(TYPES):
    r = i // 2
    c = i % 2
    ax[r][c].set_aspect("equal")
    ax[r][c].set_axis_off()
    ax[r][c].set_title("Studenti ogni mille ({})".format(t))
    it.plot(ax=ax[r][c], column='copertura ' + t, cmap='YlOrRd', scheme='quantiles', legend=True)
    
fig.savefig('italia.png')    
plt.show()    
No description has been provided for this image

Il Bebras nel mondo (dati 2023)

Dati UNESCO 2022 da: http://data.uis.unesco.org

In [39]:
unesco = pd.read_csv('unesco.csv')

unesco_tot = unesco.groupby('Country').sum()['Value']

w = gpd.read_file("world.json")
w = w.set_index("name")

with open("wbebras.json", "r") as t:
    wbebras = pd.DataFrame(pd.read_json(t, convert_axes=True, orient='index'))

wbebras['unesco'] = float('nan')

for c in wbebras.index:
    if c in unesco_tot:
        wbebras.at[c, 'unesco'] = float(unesco_tot[c])

wbebras['copertura'] = 1000 * wbebras["bebras"] / wbebras["unesco"]    
    

for i in wbebras.index:
    try:
        w.loc[i, "bebras"] = wbebras.loc[i, "bebras"]
        w.loc[i, "unesco"]   = wbebras.loc[i, "unesco"]
        w.loc[i, "copertura"]   = wbebras.loc[i, "copertura"]
    except:
        print(i)

plt.figure(figsize=(20,20))
ax = plt.subplot(212)
ax.set_aspect("equal")
ax.set_axis_off()
ax.set_title(f"Partecipanti ogni 1000 studenti (dati UNESCO {unesco['TIME'][0]})")       
w.dropna().plot(ax=ax,column='copertura', cmap='Blues', scheme='quantiles', legend=True)


ax = plt.subplot(211)
ax.set_aspect("equal")
ax.set_axis_off()
ax.set_title("Partecipanti Bebras 2023")       
p = w.dropna(subset=["bebras"]).plot(ax=ax,column='bebras', cmap='YlOrRd', scheme='quantiles', legend=True)
plt.show()
No description has been provided for this image

Numeri assoluti

In [40]:
display(wbebras.sort_values("bebras",ascending=False)[["bebras","unesco","copertura"]])
bebras unesco copertura
France 686179 2.091625e+07 32.806027
Germany 517782 1.981358e+07 26.132687
United Kingdom of Great Britain and Northern Ireland 408469 2.233629e+07 18.287232
Czechia 216803 2.918822e+06 74.277568
India 210006 5.408922e+08 0.388258
Ukraine 186446 1.695406e+06 109.971299
Taiwan 176936 NaN NaN
China 158682 4.035212e+08 0.393243
Slovakia 129939 1.381396e+06 94.063542
Portugal 105150 2.654846e+06 39.606817
Egypt 82448 2.763649e+07 2.983302
Republic of Korea 73562 1.061291e+07 6.931372
Uruguay 71275 1.294786e+06 55.047707
Serbia 64352 1.514738e+06 42.483915
Viet Nam 62640 3.763225e+07 1.664530
Austria 57970 2.084666e+06 27.807815
Lithuania 55223 7.031040e+05 78.541724
Croatia 49065 9.516840e+05 51.555979
Italy 48193 1.453918e+07 3.314698
Indonesia 46400 1.118278e+08 0.414923
Switzerland 46147 2.310532e+06 19.972457
Hungary 41595 2.362620e+06 17.605455
Saudi Arabia 36573 1.342873e+07 2.723490
Canada 31607 1.020958e+07 3.095819
Latvia 30458 4.844920e+05 62.865847
Slovenia 28872 5.759160e+05 50.132311
United States of America 27490 9.743885e+07 0.282126
Australia 27090 9.605306e+06 2.820316
Poland 20512 9.516956e+06 2.155311
North Macedonia 18370 5.182160e+05 35.448539
Uzbekistan 17658 1.297386e+07 1.361044
Netherlands 15802 5.513390e+06 2.866113
South Africa 15493 2.602258e+07 0.595368
Brazil 14394 7.481081e+07 0.192405
Romania 12433 4.625432e+06 2.687965
Ireland 12338 2.010996e+06 6.135268
Mexico 11526 5.322944e+07 0.216534
Argentina 11440 1.932641e+07 0.591936
Colombia 11055 1.797992e+07 0.614853
Pakistan 7879 7.944248e+07 0.099179
Thailand 7797 1.910819e+07 0.408045
Estonia 6352 3.669347e+05 17.310984
Algeria 5830 2.110341e+07 0.276259
Bosnia and Herzegovina 5814 7.461180e+05 7.792333
Azerbaijan 5395 3.338378e+06 1.616054
Japan 5016 2.594533e+07 0.193330
Malaysia 4981 1.131612e+07 0.440169
Belgium 4517 3.936128e+06 1.147574
Finland 4361 1.800826e+06 2.421667
Syrian Arab Republic 3830 6.983128e+06 0.548465
Peru 3544 1.363291e+07 0.259959
Iceland 3366 1.387640e+05 24.257012
New Zealand 3335 1.815482e+06 1.836977
Türkiye 3121 3.454113e+07 0.090356
Philippines 3099 5.060718e+07 0.061236
Montenegro 2959 1.889980e+05 15.656250
Jamaica 2195 7.952320e+05 2.760201
Kosovo 2174 NaN NaN
Iran 1909 NaN NaN
Cyprus 1874 2.310780e+05 8.109816
Puerto Rico 1865 NaN NaN
Spain 1818 1.301531e+07 0.139682
Dominican Republic 1421 4.052346e+06 0.350661
Sweden 891 3.773755e+06 0.236104
Bulgaria 781 1.434128e+06 0.544582
Cuba 765 2.979674e+06 0.256739
Paraguay 518 2.623744e+06 0.197428
Singapore 434 8.046200e+05 0.539385
Palestine 371 2.716820e+06 0.136557
Cambodia 57 6.517412e+06 0.008746
Israel 0 3.839150e+06 0.000000
El Salvador 0 2.091200e+06 0.000000
In [41]:
print("In totale nel mondo {} partecipanti".format(wbebras['bebras'].sum()))
In totale nel mondo 3936642 partecipanti
In [ ]: