momente şi schiţe de informatică

Statistici pe judeţ, mediu şi grupe de medii, folosind R (partea I)

Creat: 2016/mar       Comentarii

Evaluare naţională | R

Începând cu [1] şi [2] folosim R şi instrumentăm "examenul de evaluare naţională" din 2015. Din [2] deducem că aproape 80% dintre elevi au obţinut medii peste 5 şi cam 13% dintre aceştia au medii în intervalul [9, 10] - ceea ce poate să pară mulţumitor; dar la fel de bine citind, faptul că o cincime de absolvenţi de învăţământ obligatoriu primesc medii sub 5 (deşi în cataloage au toţi peste 5), iar media generală a examenului este abia 6.78 - poate îndreptăţi o stare de alarmă generală (mai ţinând seama şi de nivelul rudimentar al subiectelor): învăţământul nostru "general şi obligatoriu" promovează şi produce mediocritate şi submediocritate.

Faţă de [1] şi [2] ar mai fi de investigat (poate aflăm ceva nou?) repartiţia rezultatelor după "Mediu" - un factor cu nivelele "RURAL" şi "URBAN", din structura de date evna constituită în [1] (şi salvată pe la începutul lui [2], în fişierul "evna.RData"). De exemplu, la judeţul Vaslui avem din [2] media 6.296, cu 27.22% medii sub 5 şi pe de altă parte - avem această structură de referinţă: trei municipii, două oraşe, 81 comune, 465 localităţi şi 533 unităţi şcolare; ar fi de văzut dacă şi în ce măsură s-ar explica nivelul mediilor prin rangul localităţilor unde se află şcolile din care provin elevii…

Recuperăm setul de date 'evna' şi îl reducem la variabilele care ne interesează acum - codul judeţului, mediul în care se încadrează şcoala din care provine candidatul şi media finală a acestuia:

load('evna.RData')
evna <- subset(evna, select=c('Cod_siiir', 'Mediu', 'Media'))
colnames(evna) <- c('jud', 'Mediu', 'media')

Inspectăm structura de date rezultată şi constatăm că 'media' este un "factor":

> str(evna)
'data.frame':	163418 obs. of  3 variables:
 $ jud  : Factor w/ 42 levels "01","02","03",..: 40 40 40 40 40 40 40 40 40 40 ...
 $ Mediu: Factor w/ 2 levels "RURAL","URBAN": 2 2 2 2 2 2 2 2 2 2 ...
 $ media: Factor w/ 705 levels "","1","10","1.02",..: 135 313 261 467 419 367 303 ...
> 

Transformăm factorul 'media' în variabilă de tip numeric şi instituim (folosind funcţia cut()) variabila 'gap' - "factor" cu nivelele [1, 5), [5, 6), ..., [9, 10], prin care clasificăm mediile respective:

evna$media <- as.numeric(as.character(evna$media))
evna$gap <- cut(evna$media, breaks=c(1, 5:9, 10.01), right=FALSE)

Extragem aleatoriu un număr de rânduri de date, pentru a arăta structurarea actuală a datelor:

> evna[sample(nrow(evna), 3), ]
       jud Mediu media   gap
139749  29 RURAL  8.55 [8,9)  # elev de la o şcoală din mediul rural, jud. Prahova, cu media între 8 şi 9
30137   04 URBAN  5.65 [5,6)  # elev de la o şcoală din mediul urban, jud. Bacău, cu media în [5, 6)
35887   40 URBAN  8.57 [8,9)
> 

Avem de obţinut frecvenţa mediilor din fiecare interval, pentru cele două categorii de mediu, din fiecare judeţ. În acest scop, vom folosi unele funcţii din pachetele plyr şi reshape2:

library(plyr); library(reshape2)
evna.gap.freq <- ddply(evna, .(jud, Mediu, gap), summarise, freq=length(media))

Am angajat funcţia ddply() pentru a grupa după judeţ, mediu şi interval de medii, determinând pentru fiecare astfel de grup de linii de date numărul de elevi corespunzător, în noua variabilă 'freq':

> head(evna.gap.freq, 7)
  jud Mediu    gap  freq
1  01 RURAL  [1,5)   334  # 334 elevi din jud. Alba, din mediul rural, au medii [1, 5)
2  01 RURAL  [5,6)   171
3  01 RURAL  [6,7)   178
4  01 RURAL  [7,8)   175
5  01 RURAL  [8,9)   141
6  01 RURAL [9,10)    98  # de fapt (din definiţia 'cut()' mai sus) [9, 10.01) - încât este inclus şi 10
7  01 RURAL   <NA>    46  # 46 elevi din jud. Alba, din mediul rural, au lipsit la o probă sau alta
> 

Avem câte 14 totalizări pentru fiecare judeţ (7 la 'RURAL' şi 7 la 'URBAN'), exceptând 'M.Bucureşti' la care avem numai 7 - deci evna.gap.freq are exact 41*14+7 = 581 linii de date; ultimele 2*14 dintre acestea corespund (câte 14) judeţelor Călăraşi (de cod 51) şi Giurgiu (de cod 52).

Pentru a putea compara judeţele între ele vom avea nevoie de procente, în loc de "freq". Mai întâi, grupăm şi contorizăm după judeţ şi mediu (şi restructurăm liniile, prin funcţia dcast()):

jud.mediu <- ddply(evna, .(jud, Mediu), summarise, freq=length(media))
jud.mediu <- dcast(jud.mediu, jud ~ Mediu)

Structura de date jud.mediu obţinută astfel conţine câte o linie pentru fiecare judeţ, cu numărul de elevi participanţi la examen din mediul rural şi respectiv din mediul urban, iar liniile respective sunt în aceeaşi ordine ca şi codurile judeţelor:

> jud.mediu
   jud RURAL URBAN
1   01  1143  1701
2   02  1449  1914
... ... ... ...
27  27  3196  1662
... ... ... ...
39  39  1849  1112
40  40    NA 12052
41  51  1516   857
42  52  1743   686
> 

Pentru a referi aceste 42 de linii din cele 581 de linii ale setului evna.gap.freq, adăugăm acestuia din urmă coloana 'jud.n' constituită succesiv (prin angajarea funcţiei rep()) din 14 valori 1, 14 valori 2, ..., 14 valori 39, 7 valori 40, 14 valori 41 şi 14 valori 42:

evna.gap.freq$jud.n <- c(rep(1:39, each=14), rep(40, 7), rep(41:42, each=14))

De exemplu, linia 366 din evna.gap.freq arată că 501 elevi din mediul rural din judeţul Neamţ (codul 27) au medii în intervalul [5, 6); întrucât la intrarea 27 în jud.mediu avem în coloana 'RURAL' valoarea 3196 (reprezentând numărul total de participanţi din mediul rural din judeţul Neamţ), rezultă că mediile [5, 6) au în cazul de faţă frecvenţa relativă 501/3196=0.15676 (15.67%):

> evna.gap.freq[sample(nrow(evna.gap.freq), 3), ]
    jud Mediu    gap freq jud.n
366  27 RURAL  [5,6)  501    27  # linia 27 'jud.mediu' are RURAL=3196, deci frecvenţa relativă = 501/3196
504  36 URBAN   <NA>    7    36
377  27 URBAN [9,10)  523    27  # frecvenţa relativă pentru [9,10] pe 'URBAN' va fi 523/1662
> 

Angajând funcţia split(), despărţim evna.gap.freq în două părţi, după valorile factorului 'Mediu' şi determinăm pentru fiecare frecvenţele relative (aşa cum am exemplificat mai sus, împărţind valorile din coloana "freq" la valorile din "jud.mediu" de pe linia indicată de câmpul "jud.n", coloana 2 pentru "RURAL" şi respectiv coloana 3 pentru "URBAN") - iar apoi reunim părţile, folosind funcţia unsplit():

evna.spl <- split(evna.gap.freq, evna.gap.freq$Mediu)
evna.spl$RURAL$freq <- evna.spl$RURAL$freq / jud.mediu[evna.spl$RURAL$jud.n, 2]
evna.spl$URBAN$freq <- evna.spl$URBAN$freq / jud.mediu[evna.spl$URBAN$jud.n, 3]
evna.gap.proc <- unsplit(evna.spl, evna.gap.freq$Mediu)

Încheiem întregul demers eliminând coloana "de lucru" 'jud.n' şi schimbând codurile de judeţ cu denumirile obişnuite, preluate dintr-un set de date constituit anterior în [1]:

evna.gap.proc$jud.n <- NULL
levels(evna.gap.proc$jud) <- jud.csp$judeţ

Redăm parţial repartiţia pe judeţe, mediu de provenienţă şi intervale de medii care ne-a rezultat prin cele de mai sus:

> evna.gap.proc
                jud Mediu    gap    freq
1              Alba RURAL  [1,5) 0.29221  # 29.22% medii sub 5 în mediul rural, judeţul Alba
2              Alba RURAL  [5,6) 0.14961
... ... ...
6              Alba RURAL [9,10) 0.08574
7              Alba RURAL   <NA> 0.04024  # 4.02% absenţi, mediul rural, jud. Alba
8              Alba URBAN  [1,5) 0.11640  # 11.64% medii sub 5 în mediul urban, judeţul Alba
9              Alba URBAN  [5,6) 0.11052
... ... ...
13             Alba URBAN [9,10) 0.24397
14             Alba URBAN   <NA> 0.01117  # 1.11% absenţi, mediul urban, jud. Alba
... ... ...
547     M.Bucureşti URBAN  [1,5) 0.10919
... ... ...
552     M.Bucureşti URBAN [9,10) 0.28684
553     M.Bucureşti URBAN   <NA> 0.00514
... ... ...
568         Giurgiu RURAL  [1,5) 0.37349
... ... ...
580         Giurgiu URBAN [9,10) 0.16618
581         Giurgiu URBAN   <NA> 0.02041
> 

Schimbăm numele (ne pare mai simplu şi mai sugestiv '.jMgf' decât '.gap.proc') şi salvăm în directorul de lucru curent, structura de date respectivă:

evna.jMgf <- evna.gap.proc
save(evna.jMgf, file='evna.jMgf.RData')

Urmează să ne ocupăm mai departe (în partea a II-a) de obţinerea şi formularea vizuală a unor statistici, pentru setul de date obţinut mai sus.

Media Dinamică

Articolul 50

Drumuri

ŞahStartTemp

25
32
17
4
19
34
14
3
26
33
16
5
31
24
15
18
35
20
2
13
27
6
9
23
30
11
8
21
28
12
22
29
10
7

Ambiţiile Cavalerului

Localităţi

Judeţ:

Constituirea unei baze de date colectând cu Python de pe web

Bliţuri

Load another random Bliţ

//slightchess

Decoraţiuni hiperbolice

SALARII 2017

//bacMath
variante BAC matematică

Bacalaureat 2015 -
de la forma microsoftizată, la R

modelare ŞAH, I-XX
construcţia unui PGN-browser()

Linux şi aplicaţii Web
în 24 de ore

Orar şcolar - exemplu
după un orar generat de "aSc Orare"

Orar Adjust
ajustează orarul şcolar