2 + 3[1] 5
10 / 4[1] 2.5
(5 + 3) * 2[1] 16
Sessió 1 · Introducció a l’estadística i primers passos amb R i RStudio
Centre d’Estudis d’Opinió
19 d’octubre del 2026
| Sessió | Data | Contingut |
|---|---|---|
| 1 | Dl. 19 d’octubre | Introducció a l’estadística. R i RStudio: tipus de dades, importar i netejar dades |
| 2 | Dt. 27 d’octubre | Estadística descriptiva i inferencial univariada: intervals de confiança i contrastos d’hipòtesis |
| 3 | Dl. 2 de novembre | Estadística bivariada: taules de contingència, prova χ² i comparació de mitjanes |
| 4 | Dl. 9 de novembre | Correlació i regressió lineal |
L’objectiu no és memoritzar codi: és entendre què fem amb les dades i interpretar bé els resultats.
Abans de la pausa
Després de la pausa
Tenim més dades que mai i més capacitat per recollir-les, organitzar-les i analitzar-les.
Però… tenir dades no equival a tenir informació ni coneixement.
L’estadística és l’eina que ens permet extreure informació valuosa de les dades, per entendre el món i prendre millors decisions.
Avui: importar i netejar · Sessions 2–4: visualitzar, modelitzar i comunicar
Resumir i presentar les dades de manera clara.
Ex.: edat mitjana de les persones usuàries d’un servei
Sessions 1–2
Treure conclusions sobre una població a partir d’una mostra.
Ex.: amb 1.000 entrevistes, estimar el suport a una política
Sessió 2
Relacionar variables, explicar o predir.
Ex.: com influeixen els estudis i l’edat en la satisfacció amb un servei públic
Sessions 3–4
Exemple
Població: la ciutadania de Catalunya
Mostra: 2.000 persones entrevistades pel CEO
L’estadística inferencial ens permet extreure conclusions sobre la població a partir de la mostra, amb una certa incertesa (marge d’error).
Exemple
Tenim dades de persones (unitat d’anàlisi: persona), però volem treure conclusions per províncies: canviem el nivell d’anàlisi agregant les dades.
Una fila = una unitat d’anàlisi. Ho tornarem a veure quan treballem amb R.
El tipus de variable determina quina anàlisi podem fer!
| Variable | Tipus |
|---|---|
| Comarca de residència | Categòrica nominal |
| Satisfacció amb el servei (molt / bastant / poc / gens) | Categòrica ordinal |
| Nombre de persones a la llar | Quantitativa discreta |
| Temps d’espera (minuts) | Quantitativa contínua |
| Simpatia cap a la UE (escala 0–10) | Quantitativa discreta (o ordinal!) |
| Codi postal | Categòrica nominal (encara que siguin números!) |
Abans d’analitzar, cal revisar:
99 o 9999, “No ho sap / No contesta”Una bona neteja evita biaixos i conclusions errònies. Avui aprendrem a fer-la amb R.
Per què programar?
El codi és la recepta de l’anàlisi:
| Excel | SPSS / Jamovi | R | |
|---|---|---|---|
| Cost | Llicència | Llicència / Gratuït | Gratuït |
| Forma de treballar | Clics i fórmules | Menús | Codi |
| Reproduïble | Difícil | Parcialment | Sí |
| Volum de dades | Limitat | Mitjà | Gran |
| Gràfics personalitzats | Limitats | Limitats | Molt flexibles |
| Corba d’aprenentatge | Suau | Suau | Més pronunciada |
El preu inicial és aprendre a escriure codi. Avui comencem!
El motor: el programa que fa els càlculs.
Es pot fer servir sol, però és poc còmode.
El tauler de comandament: l’entorn on escrivim el codi, veiem les dades, els gràfics i l’ajuda.
Necessita R instal·lat per funcionar.
Instal·lació (en aquest ordre): 1. R (cran.r-project.org) · 2. RStudio Desktop (posit.co)
Alternativa sense instal·lar res: Posit Cloud (posit.cloud), RStudio al navegador.
1 · Script (editor)
On escrivim i desem el codi (.R).
Executem amb Ctrl + Enter.
3 · Entorn (Environment)
Els objectes que tenim creats: dades, vectors, resultats…
2 · Consola
On R executa el codi i mostra els resultats.
Es pot escriure directament, però no es desa.
4 · Fitxers / Gràfics / Paquets / Ajuda
Navegador de fitxers, gràfics generats, paquets instal·lats i ajuda de les funcions.
.R)| Drecera | Què fa |
|---|---|
| Ctrl + Enter | Executa la línia (o la selecció) |
| Alt + - | Escriu <- |
| Ctrl + Shift + M | Escriu el pipe |> |
| Tab | Autocompleta noms de funcions i objectes |
| Ctrl + S | Desa l’script |
Un projecte és una carpeta amb tot el que necessitem per a una anàlisi:
sessio-1/
├── sessio_1.Rproj ← obrim això
├── dades/
│ ├── enquesta_ceo.csv
│ └── competencies_basiques.csv
└── codi/
├── 01_primers_passos.R
└── exercici_sessio_1.R
.Rproj, R sap on som"dades/enquesta_ceo.csv""C:/Users/.../Documents/...", que només funcionen al nostre ordinadorAra: descarregueu materials-sessio-1.zip de la web del curs, descomprimiu-lo, obriu sessio_1.Rproj i després codi/01_primers_passos.R.
Els resultats surten a la consola. El [1] indica que és el primer valor del resultat.
<-<- vol dir: guarda el que hi ha a la dreta amb el nom de l’esquerra. L’objecte apareix al panell Entorn.
Els noms dels objectes: sense espais ni accents, millor en minúscules i amb _ (p. ex. edat_mitjana).
Amb c() (de combinar) creem un vector:
Una funció fa una feina a partir d’uns arguments:
Per saber com funciona una funció: ?mean o F1 amb el cursor a sobre del nom.
| Tipus a R | Exemple | Tipus de variable estadística |
|---|---|---|
numeric (<dbl>) |
34, 7.5 |
Quantitativa (discreta o contínua) |
character (<chr>) |
"Girona" |
Text: identificadors, o categòrica sense preparar |
factor (<fct>) |
Poc, Molt |
Categòrica (nominal o ordinal) |
logical (<lgl>) |
TRUE, FALSE |
Sí / No |
NA |
NA |
Valor perdut (de qualsevol tipus) |
Part de la neteja de dades és aconseguir que cada variable tingui el tipus correcte.
Si no diem res, R ordena les categories alfabèticament:
[1] Poc Molt Bastant Poc
Levels: Bastant Molt Poc
NA: valors perdutsR no pot calcular la mitjana si no sap un dels valors. Li hem de dir que els ignori:
A les dades reals, els valors perduts sovint no són NA: són 99, 9999, "No contesta"… Els haurem de convertir a NA.
Un paquet afegeix funcions noves a R. És com una aplicació del mòbil:
install.packages() va entre cometes: "tidyverse". library() no en necessita.
Les dades amb què treballarem són taules (data frames o tibbles):
# A tibble: 5 × 5
nom edat sexe comarca sou
<chr> <dbl> <chr> <chr> <dbl>
1 Anna 34 D Gironès 2100
2 Pau 51 H Segrià 2800
3 Marta 28 D Barcelonès NA
4 Jordi 45 H Tarragonès 2500
5 Laia 39 D Barcelonès 1900
Cada fila és una unitat d’anàlisi (una persona) i cada columna és una variable.
| Format | Què és | Com s’importa a R |
|---|---|---|
.csv |
Text separat per comes o per punts i comes | read_csv() / read_csv2() |
.xlsx |
Excel | readxl::read_excel() |
.sav |
SPSS | haven::read_sav() |
.rds |
Format propi de R (manté els tipus) | readRDS() |
CSV “europeu”: separador ; i decimals amb coma (3,5) → read_csv2()
CSV “anglès”: separador , i decimals amb punt (3.5) → read_csv()
Tornem en 30 minuts
library(tidyverse) els carreguem tots alhora| Paquet | Per a què |
|---|---|
readr |
Importar i exportar dades |
dplyr |
Manipular dades |
ggplot2 |
Gràfics |
tidyr |
Reorganitzar taules |
forcats |
Factors |
Avui ens centrem en readr (importar i exportar) i dplyr (manipular).
Imatge: Wickham, Çetinkaya-Rundel i Grolemund, R for Data Science (2a ed.)
|>: “i després”El pipe passa el resultat de l’esquerra a la funció de la dreta. Es llegeix “i després”:
“Agafa persones, i després filtra les de més de 35 anys, i després selecciona el nom i l’edat.”
# A tibble: 5 × 5
nom edat sexe comarca sou
<chr> <dbl> <chr> <chr> <dbl>
1 Anna 34 D Gironès 2100
2 Pau 51 H Segrià 2800
3 Marta 28 D Barcelonès NA
4 Jordi 45 H Tarragonès 2500
5 Laia 39 D Barcelonès 1900
Farem servir aquesta taula de 5 persones per veure cada funció.
select(): triar columnes# A tibble: 5 × 2
nom edat
<chr> <dbl>
1 Anna 34
2 Pau 51
3 Marta 28
4 Jordi 45
5 Laia 39
filter(): triar files# A tibble: 3 × 5
nom edat sexe comarca sou
<chr> <dbl> <chr> <chr> <dbl>
1 Pau 51 H Segrià 2800
2 Jordi 45 H Tarragonès 2500
3 Laia 39 D Barcelonès 1900
== igual |
!= diferent |
> >= més gran |
< <= més petit |
!is.na(x) no és perdut |
|---|
Atenció: per comparar es fa servir == (dos iguals). Un sol = s’usa per als arguments.
rename(): canviar noms de columnes# A tibble: 5 × 5
nom edat sexe comarca salari
<chr> <dbl> <chr> <chr> <dbl>
1 Anna 34 D Gironès 2100
2 Pau 51 H Segrià 2800
3 Marta 28 D Barcelonès NA
4 Jordi 45 H Tarragonès 2500
5 Laia 39 D Barcelonès 1900
rename(nom_nou = nom_antic): el nom nou a l’esquerra.
mutate(): crear o modificar columnes# A tibble: 5 × 6
nom edat sexe comarca sou sou_anual
<chr> <dbl> <chr> <chr> <dbl> <dbl>
1 Anna 34 D Gironès 2100 29400
2 Pau 51 H Segrià 2800 39200
3 Marta 28 D Barcelonès NA NA
4 Jordi 45 H Tarragonès 2500 35000
5 Laia 39 D Barcelonès 1900 26600
Si fem servir un nom que ja existeix, la columna es modifica:
mutate() + case_when(): recodificarcase_when(condició ~ valor_nou, ...)
# A tibble: 5 × 5
nom edat sexe comarca sou
<chr> <dbl> <chr> <chr> <dbl>
1 Anna 34 Dona Gironès 2100
2 Pau 51 Home Segrià 2800
3 Marta 28 Dona Barcelonès NA
4 Jordi 45 Home Tarragonès 2500
5 Laia 39 Dona Barcelonès 1900
# A tibble: 5 × 6
nom edat sexe comarca sou grup_edat
<chr> <dbl> <chr> <chr> <dbl> <chr>
1 Anna 34 D Gironès 2100 Menys de 35
2 Pau 51 H Segrià 2800 35 o més
3 Marta 28 D Barcelonès NA Menys de 35
4 Jordi 45 H Tarragonès 2500 35 o més
5 Laia 39 D Barcelonès 1900 35 o més
persones i guarda el resultat a persones_net…
sou per salari…
# A tibble: 4 × 4
nom edat sexe salari
<chr> <dbl> <chr> <dbl>
1 Anna 34 Dona 2100
2 Pau 51 Home 2800
3 Jordi 45 Home 2500
4 Laia 39 Dona 1900
| Funció | Què fa | Exemple |
|---|---|---|
read_csv2() |
Importa un CSV (;) |
dades <- read_csv2("dades/fitxer.csv") |
glimpse() |
Mostra l’estructura | glimpse(dades) |
select() |
Tria columnes | select(edat, sexe) |
filter() |
Tria files | filter(edat >= 18) |
rename() |
Canvia noms | rename(edat = EDAT) |
mutate() |
Crea o modifica columnes | mutate(edat2 = edat^2) |
case_when() |
Recodifica (dins de mutate) |
case_when(x == 99 ~ NA, .default = x) |
write_csv2() |
Exporta a CSV (;) |
write_csv2(dades, "dades/net.csv") |
|> |
“i després” | dades |> filter(...) |> select(...) |
A partir de la taula persones (secció 9 de 01_primers_passos.R):
sou_anual (sou × 14)nom i sou_anual# A tibble: 4 × 2
nom sou_anual
<chr> <dbl>
1 Anna 29400
2 Pau 39200
3 Jordi 35000
4 Laia 26600
La Marta no surt perquè té 28 anys (i, de fet, era qui tenia el sou perdut, NA).
400 respostes i 11 variables d’una enquesta del Centre d’Estudis d’Opinió:
| Variable | Contingut |
|---|---|
ID_ANONIM |
Identificador anònim |
SEXE, PROVINCIA, ANY_NAIXEMENT, LLOC_NAIX |
Característiques sociodemogràfiques |
SIMPATIA_UE, SIMPATIA_USA, SIMPATIA_RUSSIA |
Simpatia (0 = cap, 10 = molta) |
BENESTAR_VACANCES |
Es pot permetre una setmana de vacances l’any? |
SIT_ECO_PERSONAL_1_7 |
Situació econòmica personal (de molt dolenta a molt bona) |
PREOCUPACIO_CONFLICTE |
Preocupació per un conflicte internacional (0–10) |
Fitxer: dades/enquesta_ceo.csv
Rows: 400
Columns: 1
$ `ID_ANONIM;SEXE;PROVINCIA;ANY_NAIXEMENT;LLOC_NAIX;SIMPATIA_UE;SIMPATIA_USA;SIMPATIA_RUSSIA;BENESTAR_VACANCES;SIT_ECO_PERSONAL_1_7;PREOCUPACIO_CONFLICTE` <chr> …
Una sola columna! El fitxer fa servir ; com a separador.
Rows: 400
Columns: 11
$ ID_ANONIM <chr> "n4mskryleokr", "fb1zpr4ccrou", "si4cd…
$ SEXE <chr> "Femení", "Masculí", "Masculí", "Mascu…
$ PROVINCIA <chr> "Barcelona", "Tarragona", "Barcelona",…
$ ANY_NAIXEMENT <dbl> 1992, 1977, 2007, 1971, 1977, 1999, 19…
$ LLOC_NAIX <chr> "Fora d'Espanya", "Catalunya", "Catalu…
$ SIMPATIA_UE <dbl> 7, 7, 4, 7, 7, 7, 10, 9, 5, 3, 5, 10, …
$ SIMPATIA_USA <dbl> 5, 6, 4, 5, 2, 6, 5, 5, 3, 2, 6, 10, 1…
$ SIMPATIA_RUSSIA <dbl> 6, 3, 4, 4, 4, 0, 0, 2, 3, 2, 6, 0, 0,…
$ BENESTAR_VACANCES <chr> "Sí", "Sí", "Sí", "No", "No", "Sí", "N…
$ SIT_ECO_PERSONAL_1_7 <chr> "Ni bona ni dolenta", "Més aviat bona"…
$ PREOCUPACIO_CONFLICTE <chr> "10 Molta preocupació", "6", "5", "8",…
| Problema | Solució |
|---|---|
| Noms en majúscules i llargs | rename() |
SEXE: “Femení” / “Masculí” |
mutate() + case_when() |
SIMPATIA_*: el 9999 és un valor perdut |
case_when(x == 9999 ~ NA, ...) |
| “Valor perdut per omissió de resposta” | case_when(x == "Valor..." ~ NA, ...) |
PREOCUPACIO: és text (“10 Molta preocupació”) |
case_when() + as.numeric() |
SIT_ECO: ordinal, però en text |
factor(levels = ...) |
| Volem l’edat, no l’any de naixement | mutate(edat = 2025 - any_naixement) |
enquesta_neta <- enquesta |>
select(-ID_ANONIM) |>
rename(
sexe = SEXE,
provincia = PROVINCIA,
any_naixement = ANY_NAIXEMENT,
lloc_naixement = LLOC_NAIX,
simpatia_ue = SIMPATIA_UE,
simpatia_usa = SIMPATIA_USA,
simpatia_russia = SIMPATIA_RUSSIA,
vacances = BENESTAR_VACANCES,
sit_economica = SIT_ECO_PERSONAL_1_7,
preocupacio = PREOCUPACIO_CONFLICTE
)
names(enquesta_neta) [1] "sexe" "provincia" "any_naixement"
[4] "lloc_naixement" "simpatia_ue" "simpatia_usa"
[7] "simpatia_russia" "vacances" "sit_economica"
[10] "preocupacio"
enquesta_neta <- enquesta_neta |>
mutate(
sexe = case_when(sexe == "Femení" ~ "Dona",
sexe == "Masculí" ~ "Home"),
simpatia_ue = case_when(simpatia_ue == 9999 ~ NA, .default = simpatia_ue),
simpatia_usa = case_when(simpatia_usa == 9999 ~ NA, .default = simpatia_usa),
simpatia_russia = case_when(simpatia_russia == 9999 ~ NA, .default = simpatia_russia),
vacances = case_when(vacances == "Valor perdut per omissió de resposta" ~ NA,
.default = vacances)
).default = x vol dir: tot el que no compleixi cap condició, deixa’l com estava.
preocupacio té els extrems de l’escala amb etiqueta: "0 Cap preocupació", "10 Molta preocupació".
case_when() avalua les condicions per ordre: una persona de 40 anys no compleix edat < 35, però sí edat < 50, i es queda a “35-49”.
enquesta_neta <- enquesta_neta |>
mutate(
sit_economica = case_when(
sit_economica == "Valor perdut per omissió de resposta" ~ NA,
.default = sit_economica
),
sit_economica = factor(sit_economica,
levels = c("Molt dolenta", "Dolenta", "Més aviat dolenta",
"Ni bona ni dolenta",
"Més aviat bona", "Bona", "Molt bona"))
)Rows: 400
Columns: 12
$ sexe <chr> "Dona", "Home", "Home", "Home", "Dona", "Don…
$ provincia <chr> "Barcelona", "Tarragona", "Barcelona", "Barc…
$ any_naixement <dbl> 1992, 1977, 2007, 1971, 1977, 1999, 1955, 19…
$ lloc_naixement <chr> "Fora d'Espanya", "Catalunya", "Catalunya", …
$ simpatia_ue <dbl> 7, 7, 4, 7, 7, 7, 10, 9, 5, 3, 5, 10, 8, 10,…
$ simpatia_usa <dbl> 5, 6, 4, 5, 2, 6, 5, 5, 3, 2, 6, 10, 1, 9, 4…
$ simpatia_russia <dbl> 6, 3, 4, 4, 4, 0, 0, 2, 3, 2, 6, 0, 0, 5, 2,…
$ vacances <chr> "Sí", "Sí", "Sí", "No", "No", "Sí", "No", "S…
$ sit_economica <fct> Ni bona ni dolenta, Més aviat bona, Més avia…
$ preocupacio <dbl> 10, 6, 5, 8, 6, 6, 10, 7, 5, 7, 0, 4, 8, 8, …
$ edat <dbl> 33, 48, 18, 54, 48, 26, 70, 69, 35, 41, 35, …
$ grup_edat <chr> "Menys de 35", "35-49", "Menys de 35", "50-6…
Filtrar per mirar una part de les dades:
# A tibble: 4 × 4
sexe edat simpatia_ue preocupacio
<chr> <dbl> <dbl> <dbl>
1 Dona 26 7 6
2 Home 26 10 7
3 Home 25 9 7
4 Home 20 5 6
Les eines d’IA (ChatGPT, Copilot, Claude, Gemini…) ens poden ajudar amb la sintaxi: com s’escriu una funció, què vol dir un error…
La IA escriu codi. Nosaltres decidim què volem fer i comprovem el resultat.
simpatia_ue en valors perduts”glimpse(), count()Dades: dades/competencies_basiques.csv
Mostra de 500 alumnes de l’avaluació de competències bàsiques de 6è de primària (2023). Cada fila és un alumne.
| Variable | Contingut |
|---|---|
CODI_ALUMNE |
Identificador anònim |
PCAT, PMAT, PANG |
Puntuació (0–100) en català, matemàtiques i anglès |
GENERE |
D = dona, H = home |
ANY_NAIXEMENT |
Any de naixement |
NATURALESA |
Titularitat del centre (Públic / Privat) |
HABITAT |
Mida del municipi del centre |
AREA_TERRITORIAL |
Àrea territorial del Departament d’Educació |
Les mateixes dades que farem servir a la sessió 2 per a l’estadística descriptiva.
tidyverse i importar les dades amb read_csv2()glimpse(): quantes files i columnes? De quin tipus és cada variable?select(): quedar-se amb CODI_ALUMNE, GENERE, NATURALESA, HABITAT, PCAT, PMAT i PANGrename(): noms clars en minúscules (id, genere, titularitat, habitat, nota_cat…)mutate() + case_when(): recodificar genere (D → "Dona", H → "Home")mutate() + factor(): ordenar habitat de menys a més habitantsmutate(): crear nota_mitjana (de les 3 notes) i nivell_mat amb case_when(): Baix (< 50), Mitjà (50–75), Alt (≥ 75)filter(): eliminar els alumnes sense nota de matemàtiqueswrite_csv2() a dades/competencies_basiques_net.csvexercici_sessio_1.R complet i comentatcompetencies_basiques_net.csvPer correu electrònic a joelardiacaarnau@gencat.cat
Consells
sessio_1.Rproj i després codi/exercici_sessio_1.Rglimpse()?funcio), la IA… o pregunteu!numeric, character, factor, NAread_csv2, select, filter, rename, mutate, case_when, write_csv2Propera sessió (dt. 27 d’octubre): estadística descriptiva i inferencial amb R
Introducció a l’estadística amb R · Sessió 1