Qualitat de les dades¶
Exercici data-quality-audit-annex.pdf · PDF
Fas una pregunta senzilla a la taula games: quin és el joc més antic? Ordenes per data de llançament i la resposta arriba a l'instant. Un joc d'octubre de 2014. Just darrere, un d'abril de 2004.
2014 abans que 2004. La consulta no ha fallat. No hi ha cap missatge en vermell. La taula t'ha donat una resposta errònia amb tota la tranquil·litat del món. Això és el que fan les dades brutes: no peten, menteixen en silenci. Abans de netejar res, has de saber exactament on és la brutícia. Aquesta pàgina t'ensenya a mirar.
Què aprendràs
- Posar nom als quatre tipus de dades brutes: valors absents, duplicats, tipus o formats incorrectes i valors atípics
- Comptar les cel·les buides de qualsevol columna amb
COUNT(*) - COUNT(column) - Detectar un nombre o una data que en realitat s'emmagatzema com a text, i dir què es trenca per això
- Distingir una cel·la buida que vol dir «no ho sabem» d'una que significa alguna cosa
- Escriure un inventari de brutícia: columna, tipus de brutícia, evidència, decisió
- Evitar la trampa: per què «el mateix nom» no és un duplicat i «molt gran» no és un error
Obre el cofre abans de fondre¶
La qualitat de les dades és fins on et pots refiar d'una taula per respondre la teva pregunta: els seus valors hi són, són correctes, s'escriuen d'una sola manera i no es repeteixen.
Al joc de crafting que fem servir tot l'any, la Unitat 1 era collir i saquejar: portaves els materials a casa. La Unitat 2 és el forn: preparar-los. Però ningú fon a cegues. Primer obres el cofre del botí i mires: ranures buides, el mateix objecte dues vegades, objectes trencats, una espasa amb unes estadístiques absurdes.
Una auditoria de dades és aquesta mirada. Inspecciones una taula, comptes què hi ha malament i ho apuntes, sense canviar res.
El nostre cofre és games: 26,688 jocs de Steam, un per fila, recollits del lloc d'estadístiques Steam Spy i deixats bruts a propòsit. Pots baixar el fitxer des de la pàgina de Recursos.
flowchart LR
A["<b>Auditar</b><br>obre el cofre, compta la brutícia"] --> B["<b>Decidir</b><br>arreglar, marcar o deixar"]
B --> C["<b>Netejar</b><br>el forn: les properes lliçons"]
C --> D["<b>Informar</b><br>digues què has fet i què queda"]
Compte: avui ningú arregla res
La temptació és començar a reparar el primer problema que veus. Resisteix. Un arranjament fet abans de l'auditoria és una endevinalla, i no sabràs què més has trencat. L'únic producte d'una auditoria és una llista.
Quatre tipus de brutícia¶
Gairebé tot el que pot anar malament en una taula cau en quatre grups. Cadascun té la seva manera de ser trobat.
| Tipus | Al cofre | En una taula | Com trobar-lo |
|---|---|---|---|
| Valor absent | Una ranura buida | Un NULL: cap valor |
COUNT(*) - COUNT(column) |
| Duplicat | El mateix objecte dues vegades | La mateixa cosa real en dues files | GROUP BY + HAVING COUNT(*) > 1 |
| Tipus o format incorrecte | Una espasa guardada com a imatge d'una espasa | Una data o un nombre guardats com a text; una mateixa cosa escrita de dues maneres | Mira el tipus de la columna; ordena-la; LIKE |
| Valor atípic | Un objecte amb 9.999 de dany | Un valor lluny de tots els altres. Potser un error, potser real | MIN, MAX, ORDER BY ... DESC |
Les quatre seccions següents els tracten un per un, sobre games. Cada nombre d'aquí avall surt d'executar la consulta a la taula de classe.
Valors absents: les ranures buides¶
Un valor absent és una cel·la sense res a dins. En SQL s'escriu
NULL, que vol dir «cap valor», no zero i no una paraula buida.
Ja coneixes l'eina de la Unitat 1. COUNT(*) compta files. COUNT(column) només compta les files on aquella columna no és buida. La diferència és el nombre de ranures buides.
SELECT COUNT(*) AS total,
COUNT(price) AS with_price,
COUNT(*) - COUNT(price) AS no_price
FROM games;
| total | with_price | no_price |
|---|---|---|
| 26688 | 23593 | 3095 |
Fes el mateix per a totes les columnes, en un únic SELECT, i tindràs el quadre complet:
| Columna | Cel·les buides | Part de les files |
|---|---|---|
metascore |
23,838 | 89.3% |
price |
3,095 | 11.6% |
developer |
152 | 0.6% |
publisher |
120 | 0.4% |
median_playtime |
12 | menys de 0.1% |
average_playtime |
9 | menys de 0.1% |
game |
3 | 0.01% |
number, release_date, owners |
0 | 0% |
Escriu sempre el percentatge al costat del recompte. «23,838 puntuacions buides» sembla molt. «El 89.3% de la columna és buit» et diu que la columna gairebé no hi és.
Compte: una cel·la buida no sempre és un error
Dota 2 no té preu. És un error? No: Dota 2 és gratuït. Aquest NULL porta informació. Ara mira metascore, la puntuació de crítica del lloc Metacritic: 23,838 jocs no en tenen, simplement perquè cap crític no els ha analitzat mai. Aquest NULL vol dir «desconegut».
La mateixa ranura buida, dues històries diferents i, més endavant, dos tractaments diferents. Un auditor apunta quina història és.
Valors absents disfressats¶
Algunes ranures buides no ho semblen. Prova aquestes dues:
SELECT COUNT(*) FROM games WHERE average_playtime = 0; -- 25757
SELECT COUNT(*) FROM games WHERE price = 0; -- 0
average_playtime és 0 en 25,757 files: el 96.5% de la taula. Ningú no es creu que el 96.5% dels jocs de Steam s'hagin jugat zero minuts. Aquest zero vol dir «no tenim dades». És un valor absent disfressat.
I price = 0 no troba res. Ni un sol joc costa exactament zero. Doncs on són els jocs gratuïts? Són els 3,095 amb NULL.
| Què veus | Què és | A games |
|---|---|---|
NULL |
Cap valor | price IS NULL troba 3,095 files |
0 |
Un valor: el nombre zero | price = 0 troba 0 files |
0 fet servir com a «sense dades» |
Un valor absent disfressat | average_playtime = 0 en 25,757 files |
Tipus i formats incorrectes: text disfressat¶
Un tipus de dades és la classe de valor que una columna pot contenir: nombre enter, nombre decimal, text, data. El tipus decideix què pots fer amb la columna.
Pregunta a la base de dades de què està feta cada columna:
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'games'
ORDER BY ordinal_position;
| column_name | data_type |
|---|---|
| number | bigint |
| game | text |
| release_date | text |
| price | double precision |
| owners | text |
| developer | text |
| publisher | text |
| average_playtime | double precision |
| median_playtime | double precision |
| metascore | double precision |
Dues columnes són text i no ho haurien de ser: release_date (una data) i owners (una quantitat). Això és el que va trencar la consulta de dalt de tot de la pàgina:
SELECT game, release_date FROM games ORDER BY release_date LIMIT 3;
| game | release_date |
|---|---|
| Hazard Ops | 8 Oct, 2014 |
| The Dark Legions | Apr 1, 2004 |
| Geneforge 3 | Apr 1, 2005 |
El text s'ordena com un diccionari, caràcter a caràcter. 8 va abans que qualsevol lletra, i Apr va abans de Feb perquè la A va abans que la F. Una data guardada com a text no es pot ordenar, ni filtrar per any, ni posar en un eix de temps.
Encara és pitjor. Un format és la manera com s'escriu un valor. La majoria de les dates d'aquí semblen Nov 16, 2004. Són totes així?
SELECT release_date, COUNT(*) AS n
FROM games
WHERE release_date NOT LIKE '___ %, ____' -- 3 letters, space, day, comma, 4 digits
GROUP BY release_date
ORDER BY n DESC;
42 files tenen una altra forma: 41 donen només el mes i l'any (Oct 2010 tres vegades, Jun 2009 dues...) i una està escrita al revés, 8 Oct, 2014. Una columna, tres maneres d'escriure una data.
owners té la mateixa malaltia. Només conté 13 valors diferents, i tots són intervals escrits com a text, com ara 10,000,000 .. 20,000,000. El més habitual és 0 .. 20,000, amb 17,923 jocs. Ordena'l per trobar el joc amb més propietaris i obtindràs un sense-sentit:
SELECT game, owners FROM games ORDER BY owners DESC LIMIT 3;
| game | owners |
|---|---|
| DOOM 3 | 500,000 .. 1,000,000 |
| Unreal Tournament 2004: Editor's Choice Edition | 500,000 .. 1,000,000 |
| Beyond Divinity | 500,000 .. 1,000,000 |
Dota 2, amb 100,000,000 .. 200,000,000, perd. Com a text, 5 guanya a 1, de manera que «500 mil» guanya a «100 milions».
Duplicats: el mateix objecte dues vegades¶
Un duplicat és la mateixa cosa real registrada en més d'una fila.
Hi ha algun joc dues vegades a la taula? Agrupa per nom i queda't amb els noms que apareixen més d'una vegada:
SELECT game, COUNT(*) AS n
FROM games
WHERE game IS NOT NULL
GROUP BY game
HAVING COUNT(*) > 1
ORDER BY n DESC, game;
Tornen 74 noms, que cobreixen 149 files. A dalt de tot, Dark Matter, tres vegades. Abans de dir-ne duplicat, mira-ho:
SELECT number, game, release_date, developer
FROM games WHERE game = 'Dark Matter';
| number | game | release_date | developer |
|---|---|---|---|
| 317 | Dark Matter | Oct 17, 2013 | InterWave Studios |
| 777 | Dark Matter | Feb 27, 2015 | Meridian4 |
| 770 | Dark Matter | May 4, 2018 | Barty Games |
Tres desenvolupadors, tres dates. Són tres jocs diferents que casualment comparteixen nom. Esborra'n dos i hauràs destruït dades reals.
Compte: number no és un identificador
És temptador pensar que la columna number distingeix les files. Comprova-ho: SELECT COUNT(*), COUNT(DISTINCT number) FROM games; retorna 26,688 files però només 8,846 nombres diferents. El mateix number es reutilitza en molts jocs. Una auditoria també t'explica en què no et pots basar.
Valors atípics: l'objecte amb estadístiques absurdes¶
Un valor atípic és un valor molt allunyat de tots els altres. Pot ser un error de tecleig. Però també pot ser perfectament real.
Els preus són en dòlars dels EUA. Mira els extrems de la columna:
SELECT MIN(price), MAX(price), ROUND(AVG(price)::numeric, 2) AS mean FROM games;
| min | max | mean |
|---|---|---|
| 0.49 | 595.99 | 8.95 |
El joc mitjà costa 8.95 i el més car en costa 595.99. Més de seixanta vegades la mitjana. Un error de tecleig? Mira-ho abans de decidir:
SELECT game, price, developer
FROM games ORDER BY price DESC NULLS LAST LIMIT 4;
| game | price | developer |
|---|---|---|
| ADR-Labelling Game | 595.99 | Suomen Kuljetusturva Oy |
| GameMaker Studio 2 UWP | 399.99 | YoYo Games Ltd. |
| VEGAS Pro 16 Edit Steam Edition | 399 | MAGIX Software GmbH |
| Marvelous Designer 8 for Steam | 320 | CLO Virtual Fashion |
Una eina per fer jocs, un editor de vídeo, un programa de disseny de moda en 3D. Steam també ven programari professional, i el programari és car. 27 files costen més de 100 dòlars, i són sobretot productes com aquests, no errors de tecleig.
Compte: un valor atípic no és un error
Esborra només el que puguis demostrar que és incorrecte. 595.99 és un preu real d'un producte real. Un valor atípic és una pregunta («per què aquest és tan diferent?»), i la resposta es troba mirant la fila, mai suposant.
L'inventari de brutícia¶
Un inventari de brutícia és el resultat escrit d'una auditoria: una línia per problema, cadascuna amb la seva evidència i una decisió.
Cada línia té quatre parts. La regla de la tercera és estricta: sense nombre, no hi ha evidència. «Hi ha NULLs» no és una auditoria. «3,095 NULL a price, l'11.6% de les files» sí que ho és.
Per a la decisió tens tres verbs:
| Decisió | Significat | Quan |
|---|---|---|
| Arreglar | Reparar el valor | Saps quin és el valor correcte |
| Marcar | Deixar-lo i senyalar-lo perquè ningú se n'oblidi | No saps el valor i no te l'inventaràs |
| Deixar | Mantenir-lo tal com és i apuntar-lo com a limitació | El valor és real, o no es pot fer res |
Aquest és l'inventari de games. També és el mapa de la resta de la unitat:
| Columna | Què hem trobat | Decisió | Lliçó |
|---|---|---|---|
game |
3 files sense nom | Eliminar les files: un joc sense nom no es pot identificar | Tipus i formats |
release_date |
Text, en tres formes (42 files són diferents) | Arreglar: convertir-la en una data real | Tipus i formats |
owners |
Text. Un interval, no un nombre. 13 valors | Arreglar: extreure el límit inferior com a nombre | Unitats i duplicats |
game |
74 noms apareixen més d'una vegada | Investigar: el mateix joc o el mateix nom? | Unitats i duplicats |
price |
Fins a 595.99. Real: programari venut a Steam | Deixar els valors; agrupar-los en trams | Categorització |
price |
3,095 NULL (11.6%): gratuïts |
Arreglar amb el que sabem: gratuït vol dir 0 | Imputació |
metascore |
23,838 NULL (89.3%) |
Marcar, mai inventar una puntuació | Imputació |
| playtime | 0 en 25,757 files (96.5%) | Deixar i apuntar-ho com a limitació | L'informe descriptiu |
Per què m'hauria d'importar?
Imagina que el teu cap et demana «la puntuació mitjana dels jocs de Steam». Pots calcular-la en una línia. Però l'inventari t'explica que la mitjana es basa en l'11% de la taula, i no en un 11% a l'atzar. Netejar no és fer maca la taula. És saber exactament què poden dir i què no poden dir els teus nombres.
Prova-ho: audita games tu mateix¶
Obre SQL → SQL Lab, tria la base de dades Dades classe i l'esquema public. Executa una sentència cada vegada: selecciona-la i prem Run. Si executes un bloc sencer, SQL Lab només mostra l'últim resultat.
Pas 1 — Mida i tipus. Executa SELECT COUNT(*) FROM games; i després la consulta d'information_schema.columns d'aquesta pàgina. Hauries de veure 26,688 files i dues columnes text que no haurien de ser text.
Pas 2 — Valors absents. Escriu un únic SELECT amb un COUNT(*) - COUNT(column) per a cadascuna de les deu columnes. Els teus nombres haurien de coincidir amb la taula de «Valors absents». Després executa les dues comprovacions de disfressa (average_playtime = 0 i price = 0).
Pas 3 — Formats incorrectes. Executa la consulta amb NOT LIKE i les dues consultes de owners. Hauries de poder dir quantes dates tenen una forma diferent (42) i per què DOOM 3 no és realment el joc amb més propietaris.
Pas 4 — Duplicats. Executa la consulta amb HAVING COUNT(*) > 1 i després mira les files de Dark Matter. Escriu una frase: són el mateix joc?
Pas 5 — Valors atípics. Executa la consulta de MIN/MAX i els preus més alts. Decideix, amb un motiu, si 595.99 és un error de tecleig.
SQL Lab només mostra 1,000 files. La meva taula està trencada?
No. SQL Lab limita el que mostra, no el que conté la taula. COUNT(*) sempre compta totes les files. Si COUNT(*) torna un total diferent, probablement el fitxer es va pujar dues vegades: un problema de duplicats de debò, i bo per escriure'l al teu inventari.
Idees clau¶
- Una auditoria de dades vol dir mirar i comptar sense canviar res. El seu únic producte és una llista.
- Hi ha quatre tipus de brutícia: valors absents, duplicats, tipus o formats incorrectes i valors atípics.
COUNT(*) - COUNT(column)dona les cel·les buides d'una columna. Afegeix-hi sempre el percentatge.NULLi0són coses diferents. UnNULLpot voler dir «desconegut» (metascore) o portar significat (un joc gratuït), i un0pot ser un valor absent disfressat (average_playtime).- Una data o un nombre emmagatzemats com a text s'ordenen com un diccionari i no es poden fer servir en càlculs.
- El mateix nom no és un duplicat, i un valor atípic no és un error: mira la fila abans de decidir.
- Un inventari de brutícia té quatre parts per línia: columna, tipus de brutícia, evidència amb un nombre i una decisió (arreglar, marcar o deixar).
Comprovació ràpida¶
1. Quina consulta compta les cel·les buides de la columna price?
-
SELECT COUNT(price) FROM games -
SELECT COUNT(*) - COUNT(price) FROM games -
SELECT COUNT(*) FROM games WHERE price = 0 -
SELECT MIN(price) FROM games
COUNT(*) compta totes les files i COUNT(price) salta les files on price és NULL, de manera que la diferència és el nombre de cel·les buides: 3,095. Cercar price = 0 no troba res, perquè zero és un valor i NULL és l'absència d'un valor.
2. Ordenar games per release_date posa Apr 1, 2004 abans de qualsevol data de febrer. Per què?
- Perquè abril té menys dies que febrer aquell any
- Perquè la taula es va pujar en l'ordre equivocat
- Perquè la columna s'emmagatzema com a text, i el text s'ordena alfabèticament
- Perquè
ORDER BYno funciona amb dates
release_date té el tipus de dades text, de manera que la base de dades la compara lletra a lletra: la A va abans que la F. Una columna de dates de debò s'ordenaria per temps. El tipus decideix què pots fer amb una columna, no com es veu.
3. Dota 2 té un preu NULL i la majoria de jocs tenen un metascore NULL. Quina és la diferència?
- Cap: tots dos són errors que s'han d'esborrar
- El preu és un valor atípic i el
metascoreés un duplicat - El preu buit vol dir que el joc és gratuït; el
metascorebuit vol dir que ningú no ha analitzat el joc - El preu buit és desconegut; el
metascorebuit vol dir que la puntuació és zero
La mateixa cel·la buida pot explicar dues històries. El NULL del preu porta informació (gratuït), de manera que després es pot arreglar amb el que sabem. El NULL del metascore vol dir desconegut, de manera que es marca, mai s'inventa.
4. Dark Matter apareix tres vegades a games, amb tres desenvolupadors i tres dates de llançament. Què hauria de dir l'auditoria?
- És un duplicat: queda't amb la primera fila i esborra les altres dues
- Són tres jocs diferents que comparteixen nom: queda't amb els tres
- És un valor atípic, perquè cap altre nom no apareix tres vegades
- La columna
numberdemostra que són el mateix joc
Un duplicat és la mateixa cosa real en més d'una fila. Un desenvolupador diferent i una data diferent signifiquen un joc diferent. I number no hi ajuda: només té 8,846 valors diferents per a 26,688 files, de manera que no és un identificador.
5. La fila més cara de games costa 595.99, i el preu mitjà és 8.95. Quina és la reacció correcta?
- Esborrar la fila: és òbviament un error de tecleig
- Substituir-la pel preu mitjà
- Mirar primer la fila: és programari real venut a Steam, de manera que es queda
- Ignorar-la: els valors atípics mai no afecten res
Un valor atípic és una pregunta, no una sentència. Els preus més alts corresponen a eines professionals (un motor de jocs, un editor de vídeo), que realment costen tant. Esborres només el que pots demostrar que és incorrecte.
6. Quina d'aquestes és una línia d'evidència vàlida en un inventari de brutícia?
- «La columna de preu té alguns NULLs»
- «Les dates semblen estranyes»
- «
COUNT(*) - COUNT(metascore)retorna 23,838: el 89.3% de les files no tenen puntuació» - «He arreglat la columna owners»
Sense nombre, no hi ha evidència. Una línia vàlida anomena la consulta i la xifra que ha retornat, amb un percentatge quan ajuda. I l'última opció trenca la primera regla d'una auditoria: encara no s'arregla res.
7. Reps una taula amb els socis d'un gimnàs. La columna visits_last_month és 0 per al 95% dels socis, i el gimnàs és ple cada vespre. Tria les dues afirmacions que escriuria un auditor.
- Els zeros probablement són valors absents disfressats: «sense dades», no «zero visites»
- Els zeros són valors atípics i s'han d'esborrar
- La troballa va a l'inventari amb el seu recompte i percentatge abans de canviar res
- La columna és neta, perquè no conté cap
NULL
Aquest és de nou el cas d'average_playtime: un 0 que vol dir «ningú no ho ha mesurat». Una columna sense NULL pot estar gairebé buida igualment. L'auditor escriu primer l'evidència i decideix després si arregla, marca o deixa.
Ara ja saps què és brut, i tens un pla. Hora d'encendre el forn: tot seguit, Neteja: tipus i formats, on release_date es converteix per fi en una data de debò.