Statistiche sulla partecipazione al Bebras italiano 2023/24

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'):
        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'
    if r.startswith('LOM'):
        return 'LOMBARDIA'
    if r.startswith('VALLE') or 'AOSTA' in r:
        return "VALLE D'AOSTA"
    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':
        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=2023
LAST_DAY=date(YEAR,11,13)

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")

2023-11-13: 1231 insegnanti hanno confermato la partecipazione; ci sono 28176 squadre già registrate (~84528 alunni).

In [7]:
oldeditions = (2015, 2016, 2017, "bebras_2018", "bebras_2019", "bebras_2020", "bebras_2021", "bebras_2022")
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() 
                             )))

39 insegnanti hanno già partecipato all'edizione 2015 (16% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 15.9 (deviazione standard 34).

94 insegnanti hanno già partecipato all'edizione 2016 (13% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 21.0 (deviazione standard 60).

190 insegnanti hanno già partecipato all'edizione 2017 (18% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 16.6 (deviazione standard 47).

279 insegnanti hanno già partecipato all'edizione 2018 (24% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 13.4 (deviazione standard 41).

330 insegnanti hanno già partecipato all'edizione 2019 (36% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di 10.8 (deviazione standard 37).

276 insegnanti hanno già partecipato all'edizione 2020 (55% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -21.2 (deviazione standard 76).

427 insegnanti hanno già partecipato all'edizione 2021 (54% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -15.8 (deviazione standard 44).

638 insegnanti hanno già partecipato all'edizione 2022 (66% dei partecipanti di quell'edizione), il numero di squadre è aumentato in media di -0.6 (deviazione standard 27).

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 9 edizioni: 25 insegnanti.
In [11]:
#all_editions['email']
In [12]:
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: 511; numero medio insegnanti per codice: 1.95
In [13]:
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 = date(YEAR, 11, 13) - 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 [14]:
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,7) - 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 [15]:
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,0])
    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 [16]:
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 [17]:
import json
In [18]:
CATS = ('kilo','mega','giga','tera','peta')
CATEGORIES = tuple(f'{c}' for c in CATS)
In [19]:
with open("teams.json") as t:
    teams = pd.DataFrame(json.load(t)['teams'])

oldteams = pd.DataFrame({'class': CATS,f'teams_{YEAR-1}':[3681,10379,5034,3041,2610]})
oldteams.index = oldteams['class']
del oldteams['class']


teams['macro'] = teams['class'].str.slice(0,4)
    
tdata = teams.groupby('macro').count()['login'].copy()

for i in oldteams.index:
    oldteams.loc[i]['teams_' + str(YEAR)] = 1

tdata = pd.concat([tdata, oldteams],axis=1)
tdata = tdata.reindex(index = CATEGORIES)

tdata['Incremento %'] = 100*(tdata['login']-tdata[f'teams_{YEAR-1}'])/tdata[f'teams_{YEAR-1}']
display(tdata)

print("In totale {} squadre iscritte ({:+.2f}% rispetto alle squadre iscritte nel {})".format(
    tdata['login'].sum(), 
    100*(tdata['login'].sum()-olddata['squadre'].max())/olddata['squadre'].max(), 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_2022 Incremento %
kilo 4189 3681 13.800598
mega 12074 10379 16.331053
giga 5876 5034 16.726261
tera 3469 3041 14.074318
peta 2572 2610 -1.455939
In totale 28180 squadre iscritte (+13.89% rispetto alle squadre iscritte nel 2022)

Il numero di partecipanti previsto per categoria:
class
giga    17628
kilo    12567
mega    36222
peta     7716
tera    10407
Name: login, dtype: int64
Il numero totale di partecipanti previsto è 84540.

La popolazione studentesca nazionale

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

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

all_istat
Out[23]:
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 [24]:
snames = {'E': 'primaria', 'M': 'secondaria I grado', 'S': 'secondaria II grado'}
In [25]:
FIRST=114 # 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 [26]:
import json

overview = []
for k in CATEGORIES:
    with open(f"overview-{k}.json", "r") as t:
        j = json.load(t)
        overview += j['exams']
In [27]:
dfov = pd.DataFrame(overview)
In [28]:
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 [29]:
fid = teachers.set_index('id')
fid['regione'] = fid['school_region'].map(norm_region)
gare = gare.join(fid[['regione']],on='insegnante')
In [30]:
done = gare[gare['status'] == 1]

Insegnanti partecipanti

In [31]:
len(done.groupby(['insegnante']))
Out[31]:
1128

Insegnanti per regione che hanno partecipato

In [32]:
display(done.groupby(['regione'])['insegnante'].nunique())
regione
ABRUZZO                   10
BASILICATA                25
CALABRIA                   5
CAMPANIA                 110
EMILIA-ROMAGNA            70
ESTERO                     2
FRIULI-VENEZIA GIULIA     22
LAZIO                     57
LIGURIA                   28
LOMBARDIA                277
MARCHE                    24
MOLISE                    20
PIEMONTE                  93
PUGLIA                    73
SARDEGNA                  16
SICILIA                   15
TOSCANA                   43
TRENTINO-ALTO ADIGE       41
UMBRIA                    11
VALLE D'AOSTA             43
VENETO                   142
Name: insegnante, dtype: int64

Insegnanti per categoria

In [33]:
display(done.groupby(['categoria'], observed=True)['insegnante'].nunique())
categoria
kilo    318
mega    610
giga    442
tera    156
peta    117
Name: insegnante, dtype: int64

Squadre per categoria

In [34]:
with pd.option_context('display.float_format', '{:.0f}'.format):
    display(done.groupby(['regione', 'categoria'], observed=True)['login'].count())
regione                categoria
ABRUZZO                kilo           98
                       mega           43
                       giga            9
                       tera           30
                       peta           68
BASILICATA             kilo          100
                       mega          253
                       giga          124
                       tera           22
CALABRIA               kilo           10
                       mega            5
                       giga           13
                       tera           21
                       peta            2
CAMPANIA               kilo          297
                       mega          800
                       giga          384
                       tera          221
                       peta          179
EMILIA-ROMAGNA         kilo          128
                       mega          666
                       giga          354
                       tera          223
                       peta          125
ESTERO                 mega           19
                       giga           12
FRIULI-VENEZIA GIULIA  kilo           76
                       mega           84
                       giga           21
                       tera          340
                       peta          174
LAZIO                  kilo          354
                       mega          309
                       giga          133
                       tera           38
                       peta          140
LIGURIA                kilo          136
                       mega          101
                       giga           71
                       tera           50
                       peta           68
LOMBARDIA              kilo          785
                       mega         2545
                       giga         1218
                       tera          765
                       peta          378
MARCHE                 kilo           24
                       mega          223
                       giga           58
                       tera          187
                       peta          179
MOLISE                 kilo           48
                       mega          139
                       giga           61
                       tera            4
                       peta           14
PIEMONTE               kilo          317
                       mega          852
                       giga          419
                       tera          222
                       peta           99
PUGLIA                 kilo          227
                       mega          844
                       giga          271
                       tera           43
                       peta           75
SARDEGNA               kilo           34
                       mega          282
                       giga          121
                       tera            5
                       peta           17
SICILIA                kilo           59
                       mega           59
                       giga           43
                       tera           19
                       peta           81
TOSCANA                kilo          146
                       mega          444
                       giga          154
                       tera           23
                       peta            1
TRENTINO-ALTO ADIGE    kilo          155
                       mega          512
                       giga          260
                       tera           49
                       peta           46
UMBRIA                 mega          229
                       giga           96
                       tera           69
VALLE D'AOSTA          kilo           70
                       mega          485
                       giga          258
VENETO                 kilo          550
                       mega         1329
                       giga          583
                       tera          429
                       peta          248
Name: login, dtype: int64

Studenti per categoria

In [35]:
with pd.option_context('display.float_format', '{:.0f}'.format):
    display(done.groupby(['regione', 'categoria'], observed=True)['studenti'].sum())
regione                categoria
ABRUZZO                kilo          255
                       mega           60
                       giga           12
                       tera           81
                       peta          183
BASILICATA             kilo          186
                       mega          438
                       giga          241
                       tera           44
CALABRIA               kilo           27
                       mega            0
                       giga            0
                       tera           62
                       peta            6
CAMPANIA               kilo          713
                       mega         1968
                       giga         1066
                       tera          537
                       peta          487
EMILIA-ROMAGNA         kilo          238
                       mega         1389
                       giga          773
                       tera          561
                       peta          316
ESTERO                 mega           36
                       giga           22
FRIULI-VENEZIA GIULIA  kilo          196
                       mega          167
                       giga           21
                       tera          597
                       peta          170
LAZIO                  kilo          868
                       mega          659
                       giga          274
                       tera           82
                       peta          239
LIGURIA                kilo          299
                       mega          208
                       giga          142
                       tera           95
                       peta           30
LOMBARDIA              kilo         1736
                       mega         5181
                       giga         2459
                       tera         1048
                       peta          754
MARCHE                 kilo           51
                       mega          549
                       giga          117
                       tera          467
                       peta          442
MOLISE                 kilo          132
                       mega          193
                       giga           70
                       tera            0
                       peta           26
PIEMONTE               kilo          741
                       mega         1537
                       giga          758
                       tera          644
                       peta          271
PUGLIA                 kilo          635
                       mega         2046
                       giga          662
                       tera           79
                       peta           92
SARDEGNA               kilo           91
                       mega          436
                       giga          168
                       tera           15
                       peta           30
SICILIA                kilo          162
                       mega          104
                       giga           78
                       tera           55
                       peta          231
TOSCANA                kilo          419
                       mega          907
                       giga          338
                       tera           69
                       peta            1
TRENTINO-ALTO ADIGE    kilo          386
                       mega          562
                       giga          275
                       tera           81
                       peta           91
UMBRIA                 mega          212
                       giga           88
                       tera          196
VALLE D'AOSTA          kilo          144
                       mega          984
                       giga          533
VENETO                 kilo         1127
                       mega         2750
                       giga         1287
                       tera         1064
                       peta          545
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 [36]:
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 2022)

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

In [37]:
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 2022")       
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 [38]:
display(wbebras.sort_values("bebras",ascending=False)[["bebras","unesco","copertura"]])
bebras unesco copertura
France 699310 1.655071e+07 42.252576
Germany 465097 1.684384e+07 27.612283
United Kingdom 365091 NaN NaN
Czech Republic 183564 NaN NaN
Taiwan 169608 NaN NaN
Slovakia 124558 1.113122e+06 111.899684
Ukraine 84630 6.613760e+06 12.796049
Egypt 82108 3.209263e+07 2.558469
Portugal 77853 2.126530e+06 36.610346
India 65231 3.819104e+08 0.170802
South Korea 61865 NaN NaN
Republic of Serbia 59076 NaN NaN
Lithuania 53975 5.701280e+05 94.671723
Uruguay 49362 1.006246e+06 49.055599
Croatia 48015 8.115260e+05 59.166311
Austria 44570 1.724152e+06 25.850390
Turkey 44235 NaN NaN
Switzerland 44149 1.734425e+06 25.454545
China 42517 2.765286e+08 0.153753
Italy 39933 1.211525e+07 3.296094
Saudi Arabia 38041 9.709305e+06 3.917994
Hungary 37351 1.970808e+06 18.952125
Indonesia 34315 7.999742e+07 0.428951
Uzbekistan 33328 1.198292e+07 2.781292
Slovenia 30315 4.258450e+05 71.187874
Latvia 27764 3.558790e+05 78.015280
Canada 27479 7.726015e+06 3.556685
United States of America 26943 7.481493e+07 0.360129
Vietnam 25929 NaN NaN
Australia 25504 7.408190e+06 3.442676
Netherlands 18605 4.417204e+06 4.211940
North Macedonia 16909 4.142350e+05 40.819824
Poland 16649 7.037103e+06 2.365888
Bosnia and Herzegovina 13743 6.376820e+05 21.551494
Romania 10988 3.816369e+06 2.879177
Algeria 10481 4.580288e+06 2.288284
Pakistan 9870 5.196678e+07 0.189929
Thailand 9325 1.572644e+07 0.592951
Brazil 8274 6.018698e+07 0.137472
Ireland 7947 1.459465e+06 5.445146
Palestine 7232 2.071378e+06 3.491396
Argentina 6990 1.404042e+07 0.497848
Iran 5489 NaN NaN
Finland 5191 1.400749e+06 3.705874
Colombia 5191 1.408071e+07 0.368660
Japan 5086 2.024423e+07 0.251232
Estonia 4793 2.616847e+05 18.315938
Syria 3274 NaN NaN
Belgium 3231 3.210699e+06 1.006323
Iceland 2415 1.019810e+05 23.680882
Spain 2044 9.882068e+06 0.206839
Cyprus 1898 1.694710e+05 11.199556
Jamaica 1881 6.389240e+05 2.944012
Philippines 1721 3.588851e+07 0.047954
Singapore 1599 5.638190e+05 2.836017
Dominican Republic 1119 3.181395e+06 0.351732
Bulgaria 728 1.218771e+06 0.597323
Montenegro 716 1.528770e+05 4.683504
Cuba 326 2.294565e+06 0.142075
El Salvador 63 1.602284e+06 0.039319
In [39]:
print("In totale nel mondo {} partecipanti".format(wbebras['bebras'].sum()))
In totale nel mondo 3295494 partecipanti
In [ ]: