0Pricing
Pandas & NumPy Academy · Lezione

Tipo di dati categorico

Converta le colonne stringa con pochi valori distinti nel tipo Categorical di pandas per ridurre l'uso della memoria e velocizzare le operazioni groupby.

Tipo di dati categorico è una lezione Pandas & NumPy Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Pandas & NumPy Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Che cos'è il dtype Categorical?

Il dtype Categorical di Pandas è progettato per le colonne che contengono un insieme limitato di valori distinti (bassa cardinalità), come sesso, stato, regione o categoria di prodotto. Invece di memorizzare l'intera stringa per ogni riga, Pandas memorizza una sola volta i valori distinti (chiamati categorie) e utilizza un codice intero per riga per farvi riferimento. È simile al modo in cui i database utilizzano tabelle di ricerca o tipi enum.

import pandas as pd

df = pd.DataFrame({
    'region': ['North', 'South', 'East', 'North', 'East', 'South'] * 1000
})

# Without Categorical: object dtype stores every string
print('object dtype memory:', df['region'].memory_usage(deep=True))

# With Categorical: only stores 3 unique values + integer codes
df['region_cat'] = df['region'].astype('category')
print('category dtype memory:', df['region_cat'].memory_usage(deep=True))

Creare una Series Categorical

Converta una colonna in Categorical chiamando .astype('category') su qualsiasi Series. La Series Categorical risultante memorizza i valori distinti in .cat.categories e i codici interi delle posizioni in .cat.codes. Può anche creare direttamente un Categorical con pd.Categorical() per specificare in anticipo le categorie e il loro ordine.

import pandas as pd

s = pd.Series(['low', 'high', 'med', 'high', 'low'])
s_cat = s.astype('category')

print(s_cat.cat.categories)  # Index(['high', 'low', 'med'], dtype='object')
print(s_cat.cat.codes)       # integer codes per row
# 0    1
# 1    0
# 2    2
# 3    0
# 4    1

Risparmio di memoria con Categorical

Il risparmio di memoria del dtype Categorical dipende dal rapporto di cardinalità (valori distinti ÷ righe totali). In una colonna con 5 stringhe distinte e 1.000.000 di righe, il dtype object memorizza 1 milione di puntatori a stringhe (circa 50+ byte ciascuno), mentre Categorical memorizza solo 5 stringhe più 1 milione di interi a 8 bit. Il risparmio può essere di 5-20 volte, trasformando una colonna da 50 MB in una da 2-5 MB.

import pandas as pd
import numpy as np

n = 1_000_000
statuses = np.random.choice(['active', 'inactive', 'pending'], size=n)
df = pd.DataFrame({'status': statuses})

object_mem = df['status'].memory_usage(deep=True) / 1e6
df['status'] = df['status'].astype('category')
cat_mem = df['status'].memory_usage(deep=True) / 1e6

print(f'Object dtype:    {object_mem:.1f} MB')
print(f'Category dtype:  {cat_mem:.1f} MB')
print(f'Reduction:       {object_mem/cat_mem:.1f}x')

Categorical ordinato per le classifiche

A volte le categorie hanno un ordine naturale: ad esempio, 'low' < 'medium' < 'high', oppure le taglie di una T-shirt XS < S < M < L < XL. Un Categorical ordinato rappresenta questa classificazione, abilita operatori di confronto significativi (<, >= ecc.) e garantisce che i risultati di groupby siano ordinati secondo il corretto ordine semantico anziché alfabetico.

import pandas as pd

df = pd.DataFrame({
    'priority': ['high', 'low', 'medium', 'high', 'low']
})

priority_type = pd.CategoricalDtype(
    categories=['low', 'medium', 'high'],
    ordered=True
)
df['priority'] = df['priority'].astype(priority_type)

# Comparison now works correctly
print(df['priority'] >= 'medium')
# 0     True
# 1    False
# 2     True
# 3     True
# 4    False

Ordinare i Categorical ordinati

Quando si ordina una colonna Categorical ordinata, Pandas usa l’ordine definito per le categorie anziché l’ordine alfabetico. Ciò significa che 'low' viene prima di 'medium', che a sua volta viene prima di 'high', indipendentemente dall’ordine che avrebbero come stringhe. Questo è fondamentale per produrre tabelle riepilogative e grafici ordinati correttamente.

import pandas as pd

df = pd.DataFrame({
    'severity': pd.Categorical(
        ['high', 'low', 'medium', 'low', 'high'],
        categories=['low', 'medium', 'high'],
        ordered=True
    ),
    'count': [5, 20, 8, 15, 3]
})

# sort_values respects the categorical order
print(df.sort_values('severity')[['severity', 'count']])
#   severity  count
# 1      low     20
# 3      low     15
# 2   medium      8
# 0     high      5
# 4     high      3

Velocità di GroupBy con Categorical

Pandas può ottimizzare le operazioni groupby() sulle colonne Categorical perché conosce in anticipo tutti i gruppi possibili. Questo può rendere groupby da 2 a 5 volte più veloce sui DataFrame di grandi dimensioni. Inoltre, l’uso di groupby su Categorical restituisce tutte le categorie, comprese quelle vuote, garantendo che le tabelle riepilogative contengano sempre una riga per ogni gruppo previsto, anche quando alcuni hanno zero osservazioni.

import pandas as pd
import numpy as np

np.random.seed(0)
df = pd.DataFrame({
    'region': pd.Categorical(
        np.random.choice(['North', 'South', 'East', 'West'], 10),
        categories=['North', 'South', 'East', 'West']
    ),
    'sales': np.random.randint(100, 1000, 10)
})

# observed=False shows ALL categories even empty ones
print(df.groupby('region', observed=False)['sales'].sum())

Aggiunta e rimozione di categorie

Usi l’accessor .cat per gestire l’elenco delle categorie. .cat.add_categories() aggiunge nuovi valori consentiti (utile prima di inserire nuovi dati), mentre .cat.remove_unused_categories() elimina le etichette delle categorie che non hanno righe corrispondenti, operazione utile dopo un filtraggio. Non può assegnare un valore che non è presente nelle categorie senza aggiungerlo prima.

import pandas as pd

s = pd.Categorical(['a', 'b', 'a'], categories=['a', 'b', 'c'])
s = pd.Series(s)

print(s.cat.categories)  # Index(['a', 'b', 'c'], dtype='object')
print(s.value_counts())  # a:2, b:1, c:0

# Remove unused category 'c'
s = s.cat.remove_unused_categories()
print(s.cat.categories)  # Index(['a', 'b'], dtype='object')

Ridenominazione delle etichette delle categorie

.cat.rename_categories() consente di riassegnare le etichette alle categorie senza modificare i codici sottostanti. È utile quando desidera visualizzare nomi più intuitivi (ad esempio, 'M' → 'Male') o correggere l’uso incoerente delle maiuscole nelle etichette senza riconvertire i dati in object e rimapparli. Il metodo accetta una lista (posizionale) o un dizionario (mirato).

import pandas as pd

s = pd.Series(pd.Categorical(['M', 'F', 'M', 'F'], categories=['M', 'F']))

# Rename using a dict
s = s.cat.rename_categories({'M': 'Male', 'F': 'Female'})
print(s)
# 0      Male
# 1    Female
# 2      Male
# 3    Female
print(s.cat.categories)  # Index(['Male', 'Female'], dtype='object')

Quando NON usare Categorical

Il dtype Categorical è una scelta poco adatta quando la cardinalità è elevata: se quasi ogni riga ha un valore univoco (come gli ID utente, i commenti in testo libero o gli UUID), l’indice delle categorie è quasi grande quanto i dati originali e non offre alcun risparmio di memoria. Come regola generale, usi Categorical solo quando il numero di valori univoci è inferiore a circa il 50% del totale delle righe, soprattutto quando i valori univoci sono nell’ordine delle decine o delle centinaia.

import pandas as pd
import numpy as np

df = pd.DataFrame({'user_id': range(1_000_000)})

# High-cardinality: every value is unique — don't use Categorical
object_mem = df['user_id'].astype(str).memory_usage(deep=True) / 1e6
cat_mem = df['user_id'].astype(str).astype('category').memory_usage(deep=True) / 1e6

print(f'String: {object_mem:.1f} MB')
print(f'Category: {cat_mem:.1f} MB')
# Category is WORSE for high-cardinality data!

Categorical nelle tabelle pivot e in Groupby

L’uso di Categorical garantisce una forma dell’output coerente nei risultati di groupby e delle tabelle pivot. Senza Categorical, i gruppi che per caso non contengono osservazioni vengono omessi silenziosamente dal risultato, causando possibili disallineamenti dell’output quando si confrontano sezioni diverse dei dati. Con Categorical e observed=False, tutti i gruppi compaiono sempre nell’output.

import pandas as pd

df = pd.DataFrame({
    'quarter': pd.Categorical(
        ['Q1', 'Q1', 'Q3'],
        categories=['Q1', 'Q2', 'Q3', 'Q4']
    ),
    'revenue': [100, 200, 300]
})

# observed=False includes Q2 and Q4 even though they have no rows
result = df.groupby('quarter', observed=False)['revenue'].sum()
print(result)
# quarter
# Q1    300
# Q2      0
# Q3    300
# Q4      0

Categorical e machine learning

Molti estimator di scikit-learn richiedono input numerici. Per convertire una colonna Categorical in numeri per un modello, usi .cat.codes (label encoding) o pd.get_dummies() (one-hot encoding). Il one-hot encoding evita di suggerire una relazione ordinale tra le categorie. Per le categoriche ordinate, come i livelli di priorità, è appropriato il label encoding (direttamente tramite i codici), che conserva le informazioni sull’ordine.

import pandas as pd

df = pd.DataFrame({
    'colour': pd.Categorical(['red', 'blue', 'green', 'red'])
})

# One-hot encode for unordered categories
one_hot = pd.get_dummies(df['colour'], prefix='colour')
print(one_hot)
#    colour_blue  colour_green  colour_red
# 0            0             0           1
# 1            1             0           0
# 2            0             1           0
# 3            0             0           1

Verifica rapida

Verifichi la Sua comprensione del dtype Categorical.

Riepilogo della lezione

In questa lezione ha imparato che il dtype Categorical memorizza una sola volta i valori univoci e usa codici interi per ogni riga, offrendo un notevole risparmio di memoria per le colonne con bassa cardinalità; il Categorical ordinato supporta confronti significativi e un ordinamento corretto; e groupby con observed=False include tutte le categorie, anche quelle vuote. Eviti Categorical per le colonne ad alta cardinalità. Ora vedremo come analizzare correttamente le stringhe che rappresentano date con pd.to_datetime().

Domande Frequenti

La lezione «Tipo di dati categorico» è gratuita?

Sì — il testo completo di «Tipo di dati categorico» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Pandas & NumPy Academy, passa a CoddyKit PRO. Il corso Pandas & NumPy Academy include 4 lezioni in totale.

Cosa imparerò in «Tipo di dati categorico»?

Converta le colonne stringa con pochi valori distinti nel tipo Categorical di pandas per ridurre l'uso della memoria e velocizzare le operazioni groupby. Eserciti Pandas & NumPy Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Pandas & NumPy Academy?

Non è richiesta alcuna esperienza precedente. Pandas & NumPy Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Tipo di dati categorico»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Pandas & NumPy Academy?

Sì. Ogni lezione Pandas & NumPy Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Esaminare i tipi di dati delle colonne
  2. Conversione con astype()
  3. Tipo di dati categorico
  4. Analizzare correttamente le date
← Torna a Pandas & NumPy Academy