Regex in Python applicate alle recensioni: 3 esercizi di Data Cleaning

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
parsing testo non strutturato python

Quando lavori con dati provenienti da un database aziendale, da un’API o da un file CSV, è facile immaginare che ogni informazione abbia giĂ  il formato corretto.

Nella realtĂ  succede raramente.

Una recensione può contenere:

  • un voto scritto come 5 stelle;
  • un codice prodotto scritto come SKU-12345, sku: 12345 oppure SKU 12345;
  • una data nel formato 12/03/2024, 12-03-2024 o 2024.03.12.

Per un essere umano queste differenze sono quasi irrilevanti.

Per una pipeline di dati possono diventare problemi.

Se vuoi costruire una tabella con colonne come:

recensione | voto | sku | data_acquisto

devi trasformare informazioni testuali non strutturate in dati strutturati.

È qui che entrano in gioco le espressioni regolari, o regex.

In questo laboratorio vedremo tre problemi progressivi di data cleaning applicati a un dataset di recensioni e-commerce:

  1. estrarre un voto;
  2. riconoscere un codice prodotto;
  3. normalizzare una data.

L’obiettivo non è semplicemente imparare tre regex. È imparare una logica piĂš importante:

una buona regex non deve soltanto trovare ciò che cerchiamo; deve anche evitare di riconoscere ciò che gli assomiglia.

Questo è il problema dei falsi positivi, particolarmente importante quando una regex entra in una pipeline di produzione.

PubblicitĂ 

PerchĂŠ proprio le recensioni e-commerce?

Immagina un’azienda che riceva ogni giorno 10.000 recensioni.

Ogni recensione contiene testo libero scritto dai clienti.

Un sistema di analisi vorrebbe trasformare automaticamente quel testo in variabili strutturate:

rating = 5
sku = 12345
data = 2024-03-12

A quel punto quei dati possono essere utilizzati per:

  • analizzare la soddisfazione dei clienti;
  • confrontare prodotti;
  • costruire dashboard;
  • individuare anomalie;
  • alimentare modelli di machine learning;
  • collegare le recensioni alle vendite;
  • effettuare analisi temporali.

Il problema è che il testo originale non è necessariamente standardizzato.

Questo rende le regex particolarmente utili nella fase di Extract/Transform di una pipeline ETL.


Prerequisiti teorici rapidi

Prima di iniziare, ricordiamo alcuni metacaratteri fondamentali:

Simbolo Significato Esempio
. qualsiasi carattere a.c
\d una cifra \d{4}
\w carattere alfanumerico o _ \w+
\s whitespace spazio, tab, newline
* zero o piĂš occorrenze a*
+ una o piĂš occorrenze a+
? zero o una occorrenza a?
{n} esattamente n occorrenze \d{4}
{n,m} da n a m occorrenze \d{1,2}
^ inizio stringa ^SKU
$ fine stringa 12345$
\b confine di parola \bSKU\b
(...) gruppo di cattura (\d+)
(?P<nome>...) gruppo nominato (?P<voto>\d)
(?=...) lookahead positivo \d+(?= euro)
(?<=...) lookbehind positivo (?<=voto: )\d
| OR rosso|blu

Una distinzione importante accompagnerĂ  tutti gli esercizi:

riconoscere un formato non significa necessariamente validare il dato.

Una regex può stabilire che qualcosa assomiglia a una data. Non può, da sola, sapere che il 31 febbraio non esiste.


🟢 Esercizio 1 — Estrarre il voto dalle recensioni

Costruire una variabile rating

Immagina di avere raccolto 10.000 recensioni da un marketplace.

Il testo originale potrebbe essere:

"5 stelle, prodotto eccezionale!"
"Ne do 4 stelle ma con riserva."
"Ho messo 3 stelle per la consegna lenta."

Il sistema di analisi, però, non vuole conservare soltanto il testo.

Vuole creare una colonna numerica:

rating
5
4
3

PerchĂŠ?

PerchĂŠ una volta trasformato il voto in un numero puoi calcolare:

df["rating"].mean()

oppure confrontare il rating medio fra prodotti, categorie o periodi.

Il problema è che non possiamo semplicemente cercare il carattere "5".

Una recensione potrebbe infatti contenere:

Il prodotto costa 15 euro e gli darei 4 stelle.

Il 5 di 15 non è un voto.

Questo è il primo vero problema di data cleaning:

non basta trovare un valore; bisogna trovarlo nel contesto corretto.


Strategia

Il nostro pattern deve:

  1. accettare soltanto voti da 1 a 5;
  2. permettere uno o piĂš spazi;
  3. richiedere la parola stelle;
  4. evitare di estrarre una cifra contenuta dentro un numero piĂš grande.

Possiamo quindi scrivere:

import re
from typing import Optional

VOTO_RE = re.compile(
    r"\b([1-5])\s*stelle\b",
    re.IGNORECASE
)

Vediamo il pattern pezzo per pezzo:

\b

impone un confine prima della cifra.

([1-5])

cattura una sola cifra compresa fra 1 e 5.

\s*

accetta zero o piĂš spazi.

Quindi vengono riconosciuti sia:

5 stelle

sia:

5stelle

Infine:

stelle\b

richiede la parola stelle come parola autonoma.


Funzione di estrazione

def estrai_voto(testo: str) -> Optional[int]:
    """
    Estrae il voto in stelle da una recensione.
    Restituisce None se non viene trovato.
    """
    
    match = VOTO_RE.search(testo)

    if match is None:
        return None

    return int(match.group(1))

Ora possiamo testarla:

campioni = [
    "5 stelle, prodotto eccezionale!",
    "Ne do 4 stelle ma con riserva.",
    "Ho messo 3  stelle per la consegna lenta.",
    "15 stelle se potessi",
    "Nessun voto qui"
]

for testo in campioni:
    print(f"{testo!r:45} -> {estrai_voto(testo)}")

Output:

'5 stelle, prodotto eccezionale!'             -> 5
'Ne do 4 stelle ma con riserva.'              -> 4
'Ho messo 3  stelle per la consegna lenta.'   -> 3
'15 stelle se potessi'                        -> None
'Nessun voto qui'                             -> None

PerchÊ \b è cosÏ importante?

Consideriamo:

15 stelle

Senza il confine iniziale potremmo trovare:

5 stelle

come sottostringa.

Dal punto di vista del motore regex, sarebbe perfettamente legittimo.

Dal punto di vista del business, sarebbe un errore.

Il 5 di 15 non rappresenta infatti una valutazione.

Forse potrebbe interessarti anche:  Guida a Pytrends in Python: estrarre dati da Google Trends e gestire l'errore 429

Questo è un esempio di falso positivo.

Il principio è generalizzabile:

Quando estrai dati da testo libero, devi sempre chiederti non soltanto “cosa può essere un match?”, ma anche “quali stringhe simili non devono essere considerate un match?”


PubblicitĂ 

Un caso piĂš difficile

Supponiamo di incontrare:

"Voto: 5/5 stelle"

La regex precedente trova il secondo 5.

Il risultato numerico è corretto, ma abbiamo scoperto una limitazione importante.

La regex non comprende il significato linguistico della frase.

Sa soltanto riconoscere:

5 + stelle

Non sa se quel 5 rappresenti:

  • il voto assegnato;
  • il massimo disponibile;
  • un riferimento testuale.

Questo introduce una distinzione fondamentale nel data cleaning:

la regex riconosce una struttura, non comprende necessariamente il significato del testo.


Quando usare questo approccio?

È utile quando devi estrarre rapidamente una variabile strutturata da:

  • recensioni;
  • ticket di assistenza;
  • commenti;
  • moduli testuali;
  • log;
  • descrizioni prodotto.

Se il formato diventa piĂš complesso, conviene combinare regex con regole di parsing e controlli successivi.


🟢🟡 Esercizio 2 — Estrarre codici prodotto e SKU

Collegare recensioni e catalogo prodotti

Ora immaginiamo un problema piĂš vicino a un vero progetto di Data Engineering.

L’azienda possiede un catalogo prodotti strutturato:

SKU       prodotto
12345     Smartphone X
67890     Cuffie Y
11111     Monitor Z

Contemporaneamente possiede migliaia di recensioni.

Per collegare una recensione al prodotto corretto, il codice SKU può essere presente nel testo:

"Ho ordinato SKU-12345 e funziona benissimo."
"Il codice sku: 67890 non esiste sul sito."
"SKU 11111 vs SKU#22222, entrambi ok."

Il nostro obiettivo è trasformare il testo in:

["12345", "67890", "11111", "22222"]

A questo punto gli SKU possono essere utilizzati come chiave per unire i dati della recensione con il catalogo prodotti.

Questa è una situazione tipica di data integration.


Il problema dell’errore umano

Gli utenti non seguono necessariamente lo standard aziendale.

Possiamo quindi avere:

SKU-12345
SKU 12345
SKU:12345
SKU#12345

Vogliamo essere flessibili sul separatore ma rigidi sul codice.

Questa è una strategia molto utile nel data cleaning:

tolleranza sull’input, rigiditĂ  sull’output.

Il separatore può cambiare.

Il codice, invece, deve essere composto esattamente da cinque cifre.


Pattern

SKU_RE = re.compile(
    r"\bsku[\s:#\-]*(\d{5})\b",
    re.IGNORECASE
)

La parte:

\bsku

richiede che sku inizi come parola autonoma.

Poi:

[\s:#\-]*

accetta zero o piĂš separatori.

Infine:

(\d{5})

cattura esattamente cinque cifre.

Il \b finale impedisce che venga catturata soltanto una parte di un codice piĂš lungo.


Implementazione

def estrai_sku(testo: str) -> list[str]:
    """
    Estrae tutti gli SKU composti da esattamente 5 cifre.
    """
    return [
        match.group(1)
        for match in SKU_RE.finditer(testo)
    ]

Test:

testo = """
Recensione 1: Ho ordinato SKU-12345 e funziona benissimo.
Recensione 2: il codice sku: 67890 non esiste sul sito.
Recensione 3: SKU 11111 vs SKU#22222, entrambi ok.
Recensione 4: SKU-9999999 (troppo lungo) non deve matchare.
"""

print(estrai_sku(testo))

Output:

['12345', '67890', '11111', '22222']

PerchÊ il secondo \b è importante?

Consideriamo:

SKU-9999999

Il motore potrebbe iniziare a riconoscere:

SKU-99999

che contiene effettivamente cinque cifre.

Ma non vogliamo questo risultato.

Il nostro codice richiede:

cinque cifre + confine di parola

Dopo le prime cinque cifre, però, c’è ancora una cifra.

Quindi non esiste un confine di parola.

Il match viene rifiutato.

Questo è un esempio di pattern difensivo.


PerchĂŠ finditer()?

Qui non cerchiamo un solo SKU.

Potrebbero essercene molti:

SKU-12345
SKU-67890
SKU-11111

finditer() permette di scorrere tutti i match e, soprattutto, restituisce gli oggetti Match.

Questo diventa utile quando non vuoi soltanto il valore, ma anche informazioni come:

match.start()
match.end()
match.group()

Per esempio, in una pipeline di data quality potresti voler registrare dove nel testo è stato trovato il codice.


Applicazione successiva: join

Una volta estratto:

sku = "12345"

puoi collegarlo a un catalogo Pandas:

df_recensioni.merge(
    df_prodotti,
    on="sku",
    how="left"
)

La regex, quindi, non è il risultato finale.

È il primo passaggio che permette di trasformare testo non strutturato in una chiave utilizzabile per una vera analisi dati.

PubblicitĂ 

🟡 Esercizio 3 — Normalizzare le date

Costruire una timeline delle recensioni

Ora affrontiamo un problema ancora piĂš interessante.

L’azienda vuole analizzare l’evoluzione delle recensioni nel tempo.

Potrebbe voler rispondere a domande come:

  • il rating medio è cambiato dopo un aggiornamento del prodotto?
  • le recensioni negative sono aumentate dopo un aumento di prezzo?
  • quale periodo genera piĂš reclami?
  • quanto tempo passa fra acquisto e recensione?

Per fare questo, la data deve diventare un vero campo temporale.

Il problema è che il testo può contenere:

12/03/2024
12-03-2024
12.03.2024
2024/03/12
2024.03.12

Per l’analista questi valori rappresentano date.

Per Python, prima della normalizzazione, sono semplicemente stringhe differenti.


Obiettivo

Vogliamo trasformare:

12/03/2024
12-03-2024
2024.03.12

in:

2024-03-12
2024-03-12
2024-03-12

Questo formato ISO è particolarmente utile perchÊ è non ambiguo e facilmente utilizzabile nei sistemi di elaborazione dati.


Primo problema: due strutture diverse

Abbiamo due famiglie:

GG/MM/AAAA

e:

AAAA/MM/GG

Possiamo quindi usare un’alternanza:

pattern1 | pattern2

Inoltre vogliamo che il separatore sia coerente.

Per esempio:

12/03/2024

va bene.

Ma:

12/03-2024

no.


Pattern

DATA_RE = re.compile(
    r"""
    (?P<giorno>\d{1,2})
    (?P<sep>[/\-\.])
    (?P<mese>\d{1,2})
    (?P=sep)
    (?P<anno>\d{4})

    |

    (?P<anno2>\d{4})
    (?P<sep2>[/\-\.])
    (?P<mese2>\d{1,2})
    (?P=sep2)
    (?P<giorno2>\d{1,2})
    """,
    re.VERBOSE
)

Qui compare una tecnica particolarmente importante:

(?P=sep)

È un backreference.

Forse potrebbe interessarti anche:  Guida a map() in Python: Scrivere Codice Elegante e Veloce con Esempi Pratici

Significa:

usa esattamente lo stesso separatore catturato precedentemente.

Se il primo separatore è /, anche il secondo deve essere /.


Dalla sintassi alla semantica

A questo punto abbiamo riconosciuto qualcosa che sembra una data.

Ma non abbiamo ancora dimostrato che sia una data valida.

Per esempio:

31/02/2024

rispetta perfettamente la struttura:

giorno / mese / anno

ma il 31 febbraio non esiste.

Questo è il punto metodologico piĂš importante dell’intero articolo:

regex e validazione semantica sono due problemi diversi.

La regex controlla la struttura.

datetime.date controlla la validitĂ  della data.


Implementazione

from datetime import date
from typing import Optional

def normalizza_data(testo: str) -> Optional[str]:

    match = DATA_RE.search(testo)

    if not match:
        return None

    dati = match.groupdict()

    if dati["giorno"]:
        giorno = int(dati["giorno"])
        mese = int(dati["mese"])
        anno = int(dati["anno"])

    else:
        giorno = int(dati["giorno2"])
        mese = int(dati["mese2"])
        anno = int(dati["anno2"])

    try:
        return date(
            anno,
            mese,
            giorno
        ).isoformat()

    except ValueError:
        return None

Il passaggio decisivo è:

date(anno, mese, giorno)

Se la combinazione non è valida, Python solleva ValueError.

In questo modo la pipeline separa chiaramente due livelli:

REGEX
↓
riconoscimento della struttura

DATETIME
↓
validazione della data

Questa separazione rende il codice piĂš robusto e piĂš facile da manutenere.


Test

test = [
    "Acquistato il 12/03/2024, ottimo.",
    "Ricevuto il 05-11-2023 con ritardo.",
    "Recensione del 2024.01.30 — consigliato.",
    "Data sbagliata: 31/02/2024",
    "Nessuna data"
]

for testo in test:
    print(
        f"{testo!r:45} -> "
        f"{normalizza_data(testo)}"
    )

Output:

'Acquistato il 12/03/2024, ottimo.' -> 2024-03-12
'Ricevuto il 05-11-2023 con ritardo.' -> 2023-11-05
'Recensione del 2024.01.30 — consigliato.' -> 2024-01-30
'Data sbagliata: 31/02/2024' -> None
'Nessuna data' -> None

PerchĂŠ non facciamo fare tutto alla regex?

Potremmo tentare di costruire una regex gigantesca capace di distinguere:

  • mesi da 1 a 12;
  • giorni da 1 a 31;
  • mesi con 30 giorni;
  • febbraio;
  • anni bisestili.

Ma sarebbe una pessima scelta progettuale.

La regex diventerebbe difficile da leggere, difficile da testare e difficile da modificare.

È molto piÚ efficace assegnare a ogni strumento il compito per cui è adatto:

Regex
→ riconoscimento del formato

datetime
→ validazione del calendario

Pandas
→ gestione della colonna

database
→ persistenza del dato

Questa è una lezione di progettazione software molto piÚ importante della singola regex.


Le tre lezioni dietro gli esercizi

1. Voto: difendersi dai falsi positivi

Nel primo esercizio il problema principale non era trovare una cifra.

Era evitare di scambiare:

15

per:

5

Il \b rappresenta quindi una forma di controllo della qualitĂ  dell’estrazione.

In una pipeline ETL questo è fondamentale: un falso positivo può essere molto piÚ pericoloso di un valore mancante, perchÊ può entrare nel dataset senza generare un errore evidente.


2. SKU: tollerare la variabilitĂ  dell’input

Nel secondo esercizio abbiamo separato:

ciò che può variare

-
:
spazio
#

da:

ciò che deve rimanere rigido

5 cifre

Questa è una strategia molto comune nel trattamento dei dati provenienti da utenti.

Non possiamo pretendere che l’input umano sia perfettamente standardizzato.

Possiamo però definire con precisione il formato del dato che vogliamo produrre.


3. Date: separare sintassi e semantica

Il terzo esercizio introduce il livello piĂš importante.

Una stringa può avere la forma:

31/02/2024

senza rappresentare una data reale.

La regex riconosce la sintassi.

datetime verifica la semantica.

Questo principio vale ben oltre le date.

Lo stesso approccio può essere applicato a:

  • codici fiscali;
  • numeri di telefono;
  • codici prodotto;
  • email;
  • URL;
  • identificativi;
  • numeri di documento.

Una regex può dirci che un valore ha una forma plausibile.

Non necessariamente che quel valore sia corretto nel mondo reale.


Da regex a pipeline di Data Quality

A questo punto possiamo vedere i tre esercizi come una piccola pipeline:

TESTO GREZZO
     │
     ▼
┌───────────────┐
│ Regex         │
│ riconoscimento│
└───────┬───────┘
        ▼
DATO ESTRATTO
        │
        ▼
┌───────────────┐
│ Validazione   │
│ semantica     │
└───────┬───────┘
        ▼
DATO NORMALIZZATO
        │
        ▼
┌───────────────┐
│ Pandas / DB   │
│ analisi       │
└───────────────┘

Questa è probabilmente la prospettiva piÚ interessante per chi lavora con Python e Data Science.

La regex non è il fine.

È un componente della pipeline.


Mini-quiz finale

Esercizio 1

PerchĂŠ:

re.search(...)

è piÚ adatto di:

re.match(...)

quando il voto può trovarsi in qualunque punto della recensione?

Esercizio 2

PerchĂŠ:

\b

alla fine dello SKU impedisce di estrarre le prime cinque cifre da:

SKU-9999999

?

Esercizio 3

PerchĂŠ questa stringa:

31/02/2024

può superare il controllo della regex ma deve essere rifiutata da datetime.date?

Domanda da Data Scientist

Se avessi un dataset con 1 milione di recensioni, preferiresti:

  1. applicare una regex riga per riga;
  2. normalizzare il testo prima dell’estrazione;
  3. costruire una pipeline composta da estrazione + validazione + logging degli errori?

Quale architettura sceglieresti e perchĂŠ?

Risposte al mini-quiz finale

Esercizio 1 — search() oppure match()?

La scelta corretta è:

re.search(...)

search() cerca il pattern in qualunque posizione della stringa.

Questo è esattamente ciò che ci serve quando analizziamo una recensione come:

"Prodotto molto buono, consegna rapida, 5 stelle!"

Il voto non si trova necessariamente all’inizio del testo.

Al contrario, re.match() verifica il match a partire dall’inizio della stringa.

Forse potrebbe interessarti anche:  Guida Pratica a Polars: Esercizi con Soluzioni per Analizzare Dati Velocemente

Per esempio:

re.match(r"\b([1-5])\s*stelle\b", "5 stelle, prodotto ottimo")

può trovare il voto perchÊ la stringa inizia con 5 stelle.

Ma:

re.match(r"\b([1-5])\s*stelle\b",
         "Prodotto ottimo, 5 stelle")

non trova nulla.

search(), invece, continua a cercare lungo tutta la stringa e trova il voto.

Regola pratica

Possiamo quindi ricordare:

match()
→ il pattern deve iniziare dall'inizio della stringa

search()
→ il pattern può comparire in qualunque posizione

In una pipeline di text mining questa distinzione è importante perchÊ scegliere il metodo sbagliato può produrre molti valori mancanti senza necessariamente generare un errore Python.


Esercizio 2 — Perché \b protegge lo SKU?

Consideriamo:

SKU-9999999

Il nostro pattern richiede:

SKU + separatore + esattamente 5 cifre + \b

La parte:

(\d{5})

potrebbe inizialmente sembrare sufficiente.

Infatti le prime cinque cifre di:

9999999

sono effettivamente:

99999

Senza un controllo successivo, la regex potrebbe quindi estrarre una parte di un codice che in realtĂ  non rispetta il formato previsto.

Il \b finale impedisce questo comportamento.

Dopo le prime cinque cifre c’è infatti un’altra cifra.

Una cifra è un carattere di parola (\w), quindi non c’è un confine di parola in quella posizione.

Il match viene quindi rifiutato.

PerchÊ è importante in un progetto reale?

Immagina che l’azienda abbia deciso che tutti gli SKU validi siano costituiti da cinque cifre.

Se accettassimo:

SKU-9999999

come:

99999

potremmo associare una recensione al prodotto sbagliato.

Questo è molto piÚ grave di un semplice errore di formattazione: è un problema di integrità del dato.

La regex, quindi, non sta soltanto estraendo informazioni.

Sta applicando una prima regola di data quality.


Esercizio 3 — Perché 31/02/2024 supera la regex ma viene rifiutata da datetime.date?

La regex controlla principalmente la struttura della stringa.

Nel caso:

31/02/2024

trova:

giorno = 31
mese = 02
anno = 2024

La struttura è quindi compatibile con:

GG/MM/AAAA

Ma la regex non conosce il calendario.

Non sa che febbraio 2024 ha 29 giorni e che quindi il 31 febbraio non può esistere.

Quando passiamo i valori a:

date(2024, 2, 31)

datetime esegue invece una validazione semantica della data.

La combinazione non è valida e viene generato un:

ValueError

che il nostro codice intercetta:

try:
    return date(anno, mese, giorno).isoformat()

except ValueError:
    return None

Il risultato finale è quindi:

31/02/2024
→ None

La lezione generale

Questo esempio introduce una distinzione fondamentale nel data cleaning:

VALIDAZIONE SINTATTICA
"La stringa ha una forma plausibile?"

        ↓

VALIDAZIONE SEMANTICA
"Il valore rappresentato ha realmente senso?"

La regex è molto efficace nel primo compito.

Una libreria specializzata, come datetime, è piÚ adatta al secondo.


La domanda da Data Scientist

L’ultima domanda è volutamente piĂš aperta:

Se avessi un dataset con 1 milione di recensioni, preferiresti applicare una regex riga per riga, normalizzare il testo prima dell’estrazione oppure costruire una pipeline composta da estrazione + validazione + logging degli errori?

Non esiste una risposta unica valida per qualsiasi progetto, ma per un processo di produzione la terza opzione rappresenta l’approccio piĂš completo.

Una pipeline potrebbe essere organizzata cosĂŹ:

1. TESTO GREZZO
       ↓
2. NORMALIZZAZIONE
       ↓
3. ESTRAZIONE CON REGEX
       ↓
4. VALIDAZIONE
       ↓
5. NORMALIZZAZIONE DEL VALORE
       ↓
6. LOG DEGLI ERRORI
       ↓
7. DATASET PULITO

Per esempio:

"  SKU-12345  "
        ↓
normalizzazione
        ↓
"SKU-12345"
        ↓
regex
        ↓
"12345"
        ↓
validazione
        ↓
SKU valido

Ma immaginiamo invece:

"SKU-9999999"

La regex può riconoscere che la struttura non rispetta il formato previsto.

In quel caso non dovremmo semplicemente eliminare la riga senza lasciare traccia.

Possiamo registrare l’anomalia:

record_id | campo | valore | errore
------------------------------------------------
18452     | sku   | 9999999 | formato non valido

Questo è il ruolo del logging degli errori di data quality.


PerchÊ il logging è importante?

Con 10 recensioni possiamo leggere manualmente gli errori.

Con 1 milione di recensioni non possiamo farlo.

Il sistema deve quindi permetterci di sapere:

  • quanti valori sono stati estratti;
  • quanti sono stati rifiutati;
  • quanti sono mancanti;
  • quali pattern di errore sono piĂš frequenti;
  • quali record devono essere eventualmente revisionati.

Per esempio:

Totale recensioni       1.000.000
SKU estratti              927.430
SKU mancanti                52.310
SKU non validi              20.260

Queste informazioni trasformano il semplice script regex in un vero processo di Data Quality Monitoring.

 

📚 Regex, elaborazione del testo e pulizia dei dati con Python

Per approfondire l’uso delle espressioni regolari e capire come applicarle alla ricerca, estrazione e pulizia delle informazioni nei dataset, puoi consultare queste guide pratiche:

👉 Espressioni regolari (Regex) in Python: esercizi pratici e soluzioni dettagliate

👉 Guida pratica a Regex in Python: 3 esercizi reali su DNA, sentiment e sicurezza

👉 Regex in Python: 6 esercizi pratici a difficoltà crescente

👉 Pulizia dati con Python: dal dataset sporco all’analisi affidabile con Pandas

PubblicitĂ