L’extensió Thanks del programari Mediawiki, instal·lada a la Viquipèdia en català i als altres projectes de la Fundació Wikimedia, facilita eines per que els editors s’enviïn agraïments per edicions concretes, com a manera ràpida de donar feedback positius per edicions productives, De cada agraïment queda públicament registrat l’emissor, el receptor i la data i hora.
Baixar i analitzar les dades dels agraïments pot servir per oferir una mirada a l’estructura de la comunitat d’editors i a l’hora ser un exercici interessant sobre com obtenir dades del web fent servir funcions de base R. Per tal de no entrebancar la lectura als lectors interessats en el primer objectiu (els agraïments), l’explicació sobre el codi s’ha concentrat als comentaris dins dels blocs de codi.
# Establim el nombre de pàgines que llegirem.
n <- 25
Cada pàgina del registre dóna dades de 500 agraïments. Llegim les darreres 25 pàgines per tenir dades dels darrers 12500 agraïments.
# llegim el codi html de la pàgina del registre
lseg <- "https://ca.wikipedia.org/w/index.php?title=Especial:Registre&offset=&limit=500&type=thanks&user=&page=&wpdate=&tagfilter=&wpfilters%5B0%5D=newusers"
linagr <- c()
for (i in 1:n) {
pag <- readLines(lseg,
encoding = "UTF-8")
# Guardem les línies que contenen els agraïments
linagr <- c(linagr, pag[grepl("li data-mw-logid", pag)])
# Busquem l'enllaç a la següent pàgina del registre
seg <- pag[grepl("500 anteriors", pag)]
lseg <- gsub('^.*<a href=\\"(/w/index.php\\?title=Especial:Registre&offset=.*&limit=500&type=thanks&user=&page=&wpdate=&tagfilter=&wpfilters%5B0%5D=newusers)\\" class=\\"mw-nextlink\\" title=\\"Especial:Registre\\" rel=\\"next\\">500 anteriors</a>.*$',"\\1",seg[1])
lseg <- paste0("https://ca.wikipedia.org",lseg)
lseg <- gsub("&", "&", lseg)
}
# Extraiem l'emissor i el receptor de cada agraïment
trosagr <- strsplit(linagr,"ha agraït")
usagr <- lapply(trosagr, function(x) gsub('^.*\\"Usu..?ri.?:(.*?)\\".*$',"\\1", x))
actpas <- as.data.frame(t(do.call("cbind", usagr)))
names(actpas) <- c("emissor", "receptor")
# Per a fer reproduïble l'estudi, extraiem les dates inicial i final:
dates <- gsub("^.*>(..:.*?)<.*$","\\1", c(trosagr[1], trosagr[length(trosagr)]))
# Format data per operar
adata <- function(x) {
d0 <- as.Date(x,
tryFormats = "%H:%M, %d %b %Y")
d1 <- x[is.na(d0)]
d1 <- gsub(" 202", ". 202", d1)
d1 <- as.Date(d1,
tryFormats = "%H:%M, %d %b %Y")
d0[is.na(d0)] <- d1
return(d0)
}
dates1 <- adata(dates)
periode <- dates1[1]-dates1[2]
units(periode) <- "days"
dies <- as.numeric(periode)
Les dades recollides corresponen a 12500 agraïments, que són els registrats entre 21:03, 6 juny 2021 i 22:59, 17 juny 2022 (376 dies), amb una mitjana de 33.24 agraïments per dia.
Aquests 12500 agraïments han estat enviats per 498 editors diferents cap a 1015 editors diferents (en conjunt 1195 editors diferents). Noteu el nombre notablement més gran de receptors que d’emissors.
Veiem la distribució del nombre d’agraïments emesos i rebuts per cada editor.
summary(as.vector(table(actpas$emissor)))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 1.00 2.00 25.10 8.75 1236.00
De mitjana els editors que han fet agraïments n’han fet 25.1 cada un, però la meitat d’aquests editors no n’ha fet més de 2.
hist(table(actpas$emissor), breaks="scott",
main="Agraïments emesos", xlab="Emesos", ylab="Usuaris")
Tant el sumari com l’histograma ens mostren una distribució molt asimètrica a la dreta, amb la majoria d’usuaris emetent molt pocs agraïments i amb uns pocs editors emetent-ne moltíssims. Ampliant la part baixa de l’histograma veiem que hi ha un gran nombre d’usuaris que han emès un sol agraïment:
hist(table(actpas$emissor), breaks=seq(.5,3000,1), xlim=c(0,40),
main="Agraïments emesos (detall)", xlab="Emesos", ylab="Usuaris")
Fent el mateix anàlisi amb els agraïments rebuts la conclusió és molt semblant.
summary(as.vector(table(actpas$receptor)))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 1.00 1.00 12.32 3.00 934.00
De mitjana els editors que han rebut agraïments n’han rebut 12.32 cada un, però la meitat d’aquests editors no n’ha rebut més de 1.
hist(table(actpas$receptor), breaks="scott",
main="Agraïments rebuts", xlab="Rebuts", ylab="Usuaris")
hist(table(actpas$receptor), breaks=seq(.5,3000,1), xlim=c(0,40),
main="Agraïments rebuts (detall)", xlab="Rebuts", ylab="Usuaris")
De fet, el nombre d’usuaris que han rebut un sol agraïment (587) encara és més gran que el d’usuaris que han emès un sol agraïment (206).
Busquem qui són els editors amb major nombre d’agraïments emesos i d’agraïments rebuts (al final del document hi ha una versió estesa d’aquestes taules amb més editors que no caben en aquesta secció).
# Agrïments emesos
head(sort(table(actpas$emissor), decreasing = TRUE),20)
##
## Paucabot Leptictidium TaronjaSatsuma Xavier Dengra
## 1236 1095 505 476
## Amadalvarez Alzinous Aniol General Basset
## 463 428 395 369
## Cataleirxs Pere prlpz Mercè Piqueras Capsot
## 323 320 261 255
## Alvaro Vidal-Abarca Docosong Yuanga KajenCAT
## 238 204 196 193
## Davidpar Barcelona Bsckr Castellbo
## 175 161 156 155
barplot(head(sort(table(actpas$emissor), decreasing = TRUE),18), cex.names=.6, las=2, main="Agraïments emesos")
# Agrïments rebuts
head(sort(table(actpas$receptor), decreasing = TRUE),20)
##
## Paucabot Leptictidium Pere prlpz Amadalvarez Cataleirxs
## 934 623 597 467 398
## Alzinous Xavier Dengra Amortres Docosong Medol
## 360 273 263 249 222
## Mercè Piqueras Vriullop Jordi escarre KajenCAT Pallares
## 216 193 190 185 174
## Jmrebes Llumeureka Castellbo CarlesMartin Capsot
## 158 158 138 133 132
barplot(head(sort(table(actpas$receptor), decreasing = TRUE),18), cex.names=.6, las=2, main="Agraïments rebuts")
Podem veure que una fracció important dels agraïments s’intercanvien entre els usuaris més actius:
# busquem els emissors i receptors més freqüents per no atapeir les gràfiques
frequents <- c(names(head(sort(table(actpas$emissor), decreasing = TRUE),10)),
names(head(sort(table(actpas$receptor), decreasing = TRUE),10)))
frequents <- unique(frequents)
# i agrupem els altres
actpas0 <- actpas
actpas0$emissor[! actpas0$emissor %in% frequents] <- "Altres"
actpas0$receptor[! actpas0$receptor %in% frequents] <- "Altres"
# Els representem:
cols <- c("white",rainbow(length(frequents)))
pie(sort(table(actpas0$emissor), decreasing = TRUE), col=cols, cex=.8, main="Agraïments emesos")
pie(sort(table(actpas0$receptor), decreasing = TRUE), col=cols, cex=.8, main="Agraïments rebuts")
# Normalment es considera que un gràfic de sectors és una mala alternativa davant d'un gràfic de barres
# però aquí hagués estat difícil representar el grup "Altres" al mateix gràfic de barres
# que els editors que volem individualitzar.
Havíem vist que el nombre d’emissors és més gran que el de receptors. Veiem també que les emissions d’agraïments estan concentrades en poques mans, força més concentrades que les recepcions d’agraïments.
Podem comparar les dues distribucions representant-ne la funció de distribució empírica:
plot.ecdf(table(actpas$emissor), col="blue")
plot.ecdf(table(actpas$receptor), col="red", add=TRUE)
legend("bottomright", lty=1, col=c("red", "blue"), legend=c("receptor", "emissor"))
# Si les distribucions fossin menys asimètriques un boxplot podria fer
# la mateixa funció que la ecdf.
Com s’intuïa als histogrames, la distribució del nombre d’agraïments rebuts encara és més asimètrica que la d’agraïments emesos, amb un nombre molt gran d’usuaris rebent un nombre petit agraïments.
Veiem que els emissors més freqüents d’agraïments no són exactament els receptors més freqüents, i que com a mínim hi ha una part de receptors que no han emès cap agraïment (perquè hi ha més editors rebent agraïments que emetent-ne). En aquesta secció estem interessats en comparar l’activitat de cada editor com a emissor amb la seva activitat com a receptor.
Representem el nombre d’agraïments emesos i rebuts per cadascú.
# Ajuntem en un data.frame les taules d'emissors i receptors
nagr <- merge(data.frame(nom=names(table(actpas$emissor)), emesos=as.vector(table(actpas$emissor))),
data.frame(nom=names(table(actpas$receptor)), rebuts=as.vector(table(actpas$receptor))),
all=TRUE)
nagr$emesos[is.na(nagr$emesos)] <- 0
nagr$rebuts[is.na(nagr$rebuts)] <- 0
# diagrama de dispersió
plot(emesos~rebuts, data=nagr)
abline(lm(emesos~rebuts, data=nagr), col="red", lty=2)
abline(a=0, b=1, col="blue")
# etiquetem els més freqüents
frequents <- c(names(head(sort(table(actpas$emissor), decreasing = TRUE),10)),
names(head(sort(table(actpas$receptor), decreasing = TRUE),10)))
frequents <- unique(frequents)
nagrfreq <- nagr[nagr$nom %in% frequents,]
text(nagrfreq$rebuts, nagrfreq$emesos, labels=nagrfreq$nom, cex=.6, col="darkgrey")
# llegenda
legend("bottomright", col=c("blue","red"), lty=c(1,2), legend=c("x=y","regressió"))
La línia blava separa els editors que han emès més agraïments que els que han rebut (a sobre) dels que n’han rebut més que els que han emès (a sota). Els que estan per sobre de la línia blava han de ser editors que s’esforcen a dinamitzar la comunitat i donen feedback positiu a altres editors. Per altra banda, queda a criteri del lector decidir si els que quedem clarament per sota de la línia blava som grans contribuïdors justament reconeguts o senzillament som uns desagraïts, insociables i mal educats que no agraïm res.
Seguim mirant fins a quin punt emissors i receptors són els mateixos:
emissors <- unique(actpas$emissor)
receptors <- unique(actpas$receptor)
tots <- unique(c(emissors, receptors))
er <- c(sum(emissors %in% receptors), sum(!(emissors %in% receptors)), sum(!(receptors %in% emissors)))
names(er) <- c("Emissor i receptor", "Emissor no receptor", "Receptor no emissor" )
barplot(er, main="Nombre d'editors")
O sigui, hi ha un gran nombre d’editors que reben agraïments per les seves edicions però que no agraeixen les d’altres editors, però també un nombre sorprenentment gran d’editors que emeten algun agraïment però no en reben cap.
Caldria veure com són d’actius aquests grups.
eer <- c(sum(actpas$emissor %in% receptors), sum(!(actpas$emissor %in% receptors)))
names(eer) <- c("Emissor i receptor", "Emissor no receptor")
barplot(eer, main="Nombre total d'agraïments emesos")
rer <- c(sum(actpas$receptor %in% emissors), sum(!(actpas$receptor %in% emissors)))
names(rer) <- c("Emissor i receptor", "Receptor no emissor")
barplot(rer, main="Nombre total d'agraïments rebuts")
O sigui, veiem que la gran majoria d’agraïments els reben editors que també n’emeten i, encara més, gairebé tots els agraïments són emesos per editors que també en reben. Els editors que només reben o només emeten agraïments, tot i ser un grup força gran d’editors, reben i emeten una part molt petita dels agraïments.
Aquest estudi no estaria complert sense buscar els agraïments més freqüents:
parells <- with(actpas, paste(emissor, "agraeix", receptor))
tpar <- sort(table(parells), decreasing = TRUE)
head(as.data.frame(tpar), 36)
## parells Freq
## 1 Paucabot agraeix Medol 71
## 2 Leptictidium agraeix Pere prlpz 69
## 3 Aniol agraeix Paucabot 68
## 4 Alzinous agraeix Paucabot 67
## 5 Paucabot agraeix Unapeça 52
## 6 Leptictidium agraeix Amortres 51
## 7 Xavier Dengra agraeix Pere prlpz 51
## 8 Leptictidium agraeix Cataleirxs 50
## 9 Amadalvarez agraeix Pere prlpz 49
## 10 Paucabot agraeix Alzinous 48
## 11 Paucabot agraeix Jmrebes 46
## 12 Paucabot agraeix Vriullop 46
## 13 Docosong agraeix Paucabot 44
## 14 Mercè Piqueras agraeix Pere prlpz 43
## 15 Paucabot agraeix Pere prlpz 43
## 16 Leptictidium agraeix Laurita 42
## 17 Paucabot agraeix Isidre blanc 42
## 18 Leptictidium agraeix Pallares 39
## 19 Pere prlpz agraeix Paucabot 39
## 20 Leptictidium agraeix Vallue 38
## 21 Paucabot agraeix Amadalvarez 38
## 22 Pere prlpz agraeix Amadalvarez 37
## 23 Xavier Dengra agraeix Leptictidium 37
## 24 Leptictidium agraeix Flamenc 36
## 25 Paucabot agraeix Docosong 36
## 26 Alvaro Vidal-Abarca agraeix Leptictidium 35
## 27 Leptictidium agraeix Paucabot 35
## 28 Leptictidium agraeix Pcm 35
## 29 General Basset agraeix Docosong 34
## 30 Leptictidium agraeix CarlesVA 34
## 31 Mercè Piqueras agraeix Paucabot 34
## 32 Mercè Piqueras agraeix Cataleirxs 32
## 33 Paucabot agraeix Jordi escarre 32
## 34 Xavier Dengra agraeix Paucabot 32
## 35 Capsot agraeix Llumeureka 31
## 36 Cataleirxs agraeix Pallares 31
És interessant que entre els parells més freqüents hi apareixen editors que no són entre els emissors ni receptors més freqüents. Probablement sigui un indici que un bon nombre d’agraïments s’originen en feines, converses o col·laboracions concretes.
Més amunt s’han representat els emissors i receptors més freqüents deixant-ne fora molts per motiu d’espai. Aquí es recull una versió estesa de la mateixa taula.
nagr$total <- nagr$emesos+nagr$rebuts
nagrnet <- nagr[nagr$total>10,]
nagrnet <- nagrnet[order(nagrnet$total, decreasing=TRUE),]
knitr::kable(nagrnet, row.names=FALSE)
nom | emesos | rebuts | total |
---|---|---|---|
Paucabot | 1236 | 934 | 2170 |
Leptictidium | 1095 | 623 | 1718 |
Amadalvarez | 463 | 467 | 930 |
Pere prlpz | 320 | 597 | 917 |
Alzinous | 428 | 360 | 788 |
Xavier Dengra | 476 | 273 | 749 |
Cataleirxs | 323 | 398 | 721 |
TaronjaSatsuma | 505 | 128 | 633 |
Aniol | 395 | 110 | 505 |
Mercè Piqueras | 261 | 216 | 477 |
Docosong | 204 | 249 | 453 |
General Basset | 369 | 54 | 423 |
Amortres | 133 | 263 | 396 |
Capsot | 255 | 132 | 387 |
KajenCAT | 193 | 185 | 378 |
Medol | 150 | 222 | 372 |
Yuanga | 196 | 108 | 304 |
Jmrebes | 141 | 158 | 299 |
Alvaro Vidal-Abarca | 238 | 55 | 293 |
Castellbo | 155 | 138 | 293 |
Jordi escarre | 90 | 190 | 280 |
Davidpar | 175 | 94 | 269 |
CarlesMartin | 118 | 133 | 251 |
Jove | 133 | 115 | 248 |
Flamenc | 132 | 104 | 236 |
Barcelona | 161 | 71 | 232 |
Bsckr | 156 | 56 | 212 |
Vriullop | 16 | 193 | 209 |
Pallares | 27 | 174 | 201 |
Beusson | 83 | 110 | 193 |
Vallue | 89 | 103 | 192 |
AlbertRA | 79 | 111 | 190 |
Arnaugir | 119 | 69 | 188 |
Llumeureka | 30 | 158 | 188 |
FranSisPac | 64 | 120 | 184 |
Kippelboy | 127 | 55 | 182 |
Pau Colominas | 103 | 77 | 180 |
Isidre blanc | 81 | 80 | 161 |
F3RaN | 97 | 61 | 158 |
Townie | 100 | 57 | 157 |
Laurita | 66 | 83 | 149 |
Robertgarrigos | 66 | 74 | 140 |
Unapeça | 9 | 131 | 140 |
Pau Nemo | 64 | 69 | 133 |
Sorenike | 50 | 78 | 128 |
Mcapdevila | 72 | 50 | 122 |
Jordiventura96 | 50 | 70 | 120 |
Pcm | 19 | 99 | 118 |
Loupeter | 14 | 92 | 106 |
MALLUS | 45 | 60 | 105 |
Vulcano | 76 | 28 | 104 |
Kowalskyn | 47 | 48 | 95 |
KRLS | 25 | 70 | 95 |
Manlleus | 39 | 56 | 95 |
CarlesVA | 3 | 90 | 93 |
Kette~cawiki | 46 | 47 | 93 |
Lohen11 | 32 | 56 | 88 |
Marcmiquel | 70 | 18 | 88 |
Josep Estruch Traité | 62 | 24 | 86 |
Anna maria batalla | 70 | 15 | 85 |
Jordirooca | 51 | 33 | 84 |
Sjoel | 53 | 31 | 84 |
Magenri | 32 | 49 | 81 |
Willy31igd | 34 | 43 | 77 |
Jaumellecha | 42 | 32 | 74 |
Jmarchn | 28 | 44 | 72 |
Lluis tgn | 27 | 44 | 71 |
Dragonfly137 | 32 | 37 | 69 |
Crespinell (encara no existeix) | 47 | 17 | 64 |
Joutbis | 13 | 51 | 64 |
ESM | 60 | 3 | 63 |
Solde | 29 | 33 | 62 |
Brunnaiz | 27 | 33 | 60 |
Tomeu87 | 31 | 28 | 59 |
Judesba | 38 | 18 | 56 |
Gerard Viader | 35 | 20 | 55 |
Ivan Avz F | 10 | 43 | 53 |
Walden69 | 4 | 49 | 53 |
Josu PV | 13 | 39 | 52 |
Catgirl | 19 | 30 | 49 |
Alexis900 | 5 | 43 | 48 |
Tiputini | 20 | 28 | 48 |
Varondán | 18 | 30 | 48 |
Joandrés | 17 | 28 | 45 |
Pilardenou999 | 3 | 42 | 45 |
J bullanga | 24 | 16 | 40 |
Joan Gené | 8 | 32 | 40 |
Quetz72 | 25 | 15 | 40 |
Socialdilema | 2 | 36 | 38 |
Enric | 10 | 27 | 37 |
Quelcom | 2 | 35 | 37 |
Hasley | 1 | 35 | 36 |
Misterspritz | 16 | 20 | 36 |
Symposiarch (encara no existeix) | 36 | 0 | 36 |
Jordi G | 23 | 12 | 35 |
ReginaManresa | 4 | 30 | 34 |
Mbosch | 9 | 24 | 33 |
Smalde | 12 | 21 | 33 |
Ferinancat | 13 | 19 | 32 |
Rocafera | 3 | 29 | 32 |
Maria Fullana de València | 12 | 19 | 31 |
Vador Faura (encara no existeix) | 17 | 14 | 31 |
Ignasi | 7 | 23 | 30 |
PaliGol | 14 | 15 | 29 |
Paracel63 | 23 | 6 | 29 |
Carmallola | 17 | 11 | 28 |
Culturaactiva | 19 | 8 | 27 |
Desesser | 5 | 22 | 27 |
Theklan | 7 | 20 | 27 |
Mcsmp | 10 | 16 | 26 |
Paputx | 5 | 21 | 26 |
Pdg | 10 | 15 | 25 |
Queso y aceitunas | 17 | 7 | 24 |
Xamil | 12 | 12 | 24 |
Bloguer | 9 | 14 | 23 |
Bodinejador | 13 | 10 | 23 |
Jordi Roqué | 7 | 16 | 23 |
Kuranes | 14 | 9 | 23 |
Bestiasonica | 2 | 20 | 22 |
FogueraC | 10 | 12 | 22 |
Markus2801 | 11 | 11 | 22 |
Pere Sallavinera | 10 | 12 | 22 |
Toniher | 5 | 17 | 22 |
Arnandis | 2 | 19 | 21 |
Catalaalatac | 16 | 4 | 20 |
Cpratsferre | 9 | 11 | 20 |
QuimGil | 4 | 16 | 20 |
Riumors21 (encara no existeix) | 18 | 2 | 20 |
B25es | 1 | 18 | 19 |
Caminort | 4 | 15 | 19 |
Darth vader 92 | 10 | 9 | 19 |
Enrospv | 10 | 9 | 19 |
Montesita | 2 | 17 | 19 |
Setze16 | 15 | 4 | 19 |
Sguastevi | 9 | 10 | 19 |
Jordiff | 11 | 7 | 18 |
Quelet | 0 | 18 | 18 |
Rei Momo | 13 | 5 | 18 |
Xvazquez | 1 | 17 | 18 |
Davdde | 7 | 10 | 17 |
Marinna | 11 | 6 | 17 |
Pacopac | 8 | 9 | 17 |
Paddy Mc Aloon (encara no existeix) | 2 | 15 | 17 |
SGrabarczuk (WMF) | 1 | 16 | 17 |
Victorlopezmoya | 17 | 0 | 17 |
1997z | 1 | 15 | 16 |
19Tarrestnom65 | 4 | 12 | 16 |
Galactic Thrasher | 11 | 5 | 16 |
Hiperterminal | 10 | 6 | 16 |
Kxont | 0 | 16 | 16 |
Adebalma8 (encara no existeix) | 14 | 1 | 15 |
Aemda | 12 | 3 | 15 |
Jey | 10 | 5 | 15 |
STei (WMF) | 3 | 12 | 15 |
Eduard Farre | 6 | 8 | 14 |
Lks.poch | 7 | 7 | 14 |
Or8a | 7 | 7 | 14 |
Sanmame (encara no existeix) | 0 | 14 | 14 |
Caro de Segeda | 11 | 2 | 13 |
ICR CMC (encara no existeix) | 0 | 13 | 13 |
Lluís RD (encara no existeix) | 0 | 13 | 13 |
Olímpic | 1 | 12 | 13 |
Pons | 0 | 13 | 13 |
Pundit | 3 | 10 | 13 |
Qgil-WMF | 4 | 9 | 13 |
RafelJuan | 2 | 11 | 13 |
Wakamai | 0 | 13 | 13 |
Banyeres | 2 | 10 | 12 |
Biblioaprenent | 12 | 0 | 12 |
Castell | 3 | 9 | 12 |
Edu Rne | 4 | 8 | 12 |
Josepko | 6 | 6 | 12 |
Marraco | 4 | 8 | 12 |
Desluqlop (encara no existeix) | 11 | 0 | 11 |
El Mono Español | 6 | 5 | 11 |
Herodotptlomeu | 3 | 8 | 11 |
Raspilla Demekin | 8 | 3 | 11 |