API · Pandas

Funzione Pandas DataFrame DataFrame.transpose()

La funzione Pandas DataFrame transpose() cambia le righe del DataFrame in colonne e viceversa.

In questa pagina

Usa DataFrame.transpose() per scambiare righe e colonne di un DataFrame pandas. Il DataFrame restituito usa le etichette delle righe originali come etichette delle colonne e le etichette delle colonne originali come etichette delle righe. Gli esempi di questa guida girano su pandas 3.1 e trattano anche la scorciatoia T, cosa accade ai dtype quando un DataFrame mescola numeri e testo, e come il risultato condivide la memoria con l’originale.

Sintassi di DataFrame.transpose()

Chiama il metodo sull’oggetto che vuoi trasporre: df.transpose(). Restituisce un DataFrame trasposto; l’oggetto originale resta disponibile come df.

import pandas as pd

transposed = dataframe.transpose()

La firma accetta anche *args e una parola chiave copy, entrambi mantenuti per compatibilità con l’API NumPy e con codice pandas più vecchio. Nessuno dei due serve in una chiamata normale: pandas non accetta posizioni degli assi (la sezione sugli errori mostra cosa succede se ne passi una) e pandas 3 deprecata copy perché il Copy-on-Write decide già quando i dati vengono duplicati.

Esempio: trasporre un DataFrame con DataFrame.transpose()

Questo esempio crea una piccola tabella con i nomi degli studenti, la frequenza e i voti. Dopo la chiamata, ogni colonna originale diventa una riga e ogni etichetta dell’indice originale diventa una colonna.

import pandas as pd

dataframe = pd.DataFrame(
    {
        "Attendance": [60, 100, 80, 78, 95],
        "Name": ["Olivia", "John", "Laura", "Ben", "Kevin"],
        "Obtained Marks": [90, 75, 82, 64, 45],
    }
)

transposed = dataframe.transpose()
print(transposed)

Produzione:

                     0     1      2    3      4
Attendance          60   100     80   78     95
Name            Olivia  John  Laura  Ben  Kevin
Obtained Marks      90    75     82   64     45

Le etichette aiutano a verificare la direzione dello scambio: nel risultato, Attendance, Name e Obtained Marks etichettano le righe, mentre i valori da 0 a 4 etichettano le colonne.

Trasporre un DataFrame con tipi di dati omogenei

Quando tutte le colonne contengono numeri interi, l’input ha un tipo di valore omogeneo. Trasponilo e controlla i dtype delle colonne prima e dopo, per vedere come viene rappresentato questo esempio nel tuo ambiente pandas.

import pandas as pd

dataframe = pd.DataFrame(
    {
        "A": [6, 20, 80, 78, 95],
        "B": [60, 50, 7, 67, 54],
    }
)

transposed = dataframe.transpose()
print("Original values:")
print(dataframe)
print("Transposed values:")
print(transposed)
print("Original dtypes:")
print(dataframe.dtypes)
print("Transposed dtypes:")
print(transposed.dtypes)

Produzione:

Original values:
    A   B
0   6  60
1  20  50
2  80   7
3  78  67
4  95  54
Transposed values:
    0   1   2   3   4
A   6  20  80  78  95
B  60  50   7  67  54
Original dtypes:
A    int64
B    int64
dtype: object
Transposed dtypes:
0    int64
1    int64
2    int64
3    int64
4    int64
dtype: object

Questo input ha cinque righe, etichettate da 0 a 4, e due colonne, A e B, quindi il risultato ha due righe e cinque colonne. Poiché ogni colonna di input contiene interi, le colonne trasposte mantengono il dtype int64: quando tutte le colonne di un DataFrame condividono un unico dtype, le colonne del DataFrame trasposto mantengono quel dtype. L’esempio successivo mostra cosa cambia quando non lo condividono.

Trasporre un DataFrame con tipi di dati misti

Un DataFrame può contenere colonne di tipi diversi. In questo esempio, due colonne contengono numeri e una contiene nomi. Il codice mostra i valori e i dtype prima e dopo l’operazione, così puoi esaminare il risultato per questo input.

import pandas as pd

dataframe = pd.DataFrame(
    {
        "Attendance": [60, 100, 80, 78, 95],
        "Name": ["Olivia", "John", "Laura", "Ben", "Kevin"],
        "Obtained Marks": [90, 75, 82, 64, 45],
    }
)

transposed = dataframe.transpose()
print("Original values:")
print(dataframe)
print("Transposed values:")
print(transposed)
print("Original dtypes:")
print(dataframe.dtypes)
print("Transposed dtypes:")
print(transposed.dtypes)

Produzione:

Original values:
   Attendance    Name  Obtained Marks
0          60  Olivia              90
1         100    John              75
2          80   Laura              82
3          78     Ben              64
4          95   Kevin              45
Transposed values:
                     0     1      2    3      4
Attendance          60   100     80   78     95
Name            Olivia  John  Laura  Ben  Kevin
Obtained Marks      90    75     82   64     45
Original dtypes:
Attendance        int64
Name                str
Obtained Marks    int64
dtype: object
Transposed dtypes:
0    object
1    object
2    object
3    object
4    object
dtype: object

I valori in sé si spostano senza modifiche, ma confronta i dtype: ogni colonna del DataFrame trasposto ha dtype object, comprese le colonne che contengono solo numeri. Ciascuna di quelle colonne combina ora valori provenienti dalle due colonne di interi e dalla colonna Name, e object è l’unico dtype in grado di contenerli tutti: i numeri restano presenti, ma memorizzati come oggetti Python generici invece che come valori int64.

Quando una trasposizione mista trasforma i numeri in oggetti

Questa perdita di dtype non è solo cosmetica. Le operazioni aritmetiche sull’intero DataFrame trasposto raggiungono ora le stringhe memorizzate nella riga Name e falliscono:

import pandas as pd

dataframe = pd.DataFrame(
    {
        "Attendance": [60, 100, 80, 78, 95],
        "Name": ["Olivia", "John", "Laura", "Ben", "Kevin"],
        "Obtained Marks": [90, 75, 82, 64, 45],
    }
)

transposed = dataframe.transpose()
print(transposed + 1)

Produzione:

TypeError: can only concatenate str (not "int") to str

Trasporre di nuovo ripristina la disposizione originale, ma non i dtype originali: il DataFrame ripristinato mantiene object per ogni colonna. Per tornare a lavorare con numeri veri, converti con astype() le righe che devono essere numeriche:

import pandas as pd

dataframe = pd.DataFrame(
    {
        "Attendance": [60, 100, 80, 78, 95],
        "Name": ["Olivia", "John", "Laura", "Ben", "Kevin"],
        "Obtained Marks": [90, 75, 82, 64, 45],
    }
)

transposed = dataframe.transpose()
restored = transposed.transpose()
print("Dtypes after transposing back:")
print(restored.dtypes)

numeric_rows = transposed.loc[["Attendance", "Obtained Marks"]].astype(int)
print("Dtypes of the recovered numeric rows:")
print(numeric_rows.dtypes)

Produzione:

Dtypes after transposing back:
Attendance        object
Name              object
Obtained Marks    object
dtype: object
Dtypes of the recovered numeric rows:
0    int64
1    int64
2    int64
3    int64
4    int64
dtype: object

La conversione seleziona solo le due righe numeriche. Includere la riga Name farebbe fallire astype(int) sui nomi, quindi lascia le righe di testo fuori dalla selezione.

Trasporre con la scorciatoia T

La proprietà T è la scorciatoia per la chiamata senza argomenti e restituisce lo stesso DataFrame. Su un DataFrame non quadrato, la forma mostra lo scambio a colpo d’occhio: cinque righe e due colonne diventano due righe e cinque colonne. Trasporre due volte ripristina l’originale e, per questo input omogeneo, equals() conferma che sia i valori sia i dtype sopravvivono al viaggio di andata e ritorno — a differenza dell’esempio misto qui sopra.

import pandas as pd

dataframe = pd.DataFrame(
    {
        "A": [6, 20, 80, 78, 95],
        "B": [60, 50, 7, 67, 54],
    }
)

print("Original shape:", dataframe.shape)
print("Transposed shape:", dataframe.T.shape)
print("T matches transpose():", dataframe.T.equals(dataframe.transpose()))
print("Transposing twice restores the original:", dataframe.T.T.equals(dataframe))

Produzione:

Original shape: (5, 2)
Transposed shape: (2, 5)
T matches transpose(): True
Transposing twice restores the original: True

Come il DataFrame trasposto condivide la memoria con l’originale

Un DataFrame trasposto non è una copia indipendente dei dati. Per impostazione predefinita è una vista che condivide la memoria con l’originale, come conferma numpy.shares_memory():

import numpy as np
import pandas as pd

dataframe = pd.DataFrame(
    {
        "A": [6, 20, 80, 78, 95],
        "B": [60, 50, 7, 67, 54],
    }
)

transposed = dataframe.transpose()
print("Shares memory with the original:", np.shares_memory(transposed, dataframe))

transposed.iloc[0, 0] = 999
print("Value in the transposed frame:", transposed.loc["A", 0])
print("Value in the original frame:", dataframe.loc[0, "A"])

Produzione:

Shares memory with the original: True
Value in the transposed frame: 999
Value in the original frame: 6

Condividere la memoria non significa che le modifiche si propaghino all’originale. Il Copy-on-Write, sempre attivo da pandas 3.0, copia i dati interessati alla prima scrittura, quindi l’assegnazione modifica solo il DataFrame trasposto e l’originale mantiene il suo valore. Chiama .copy() sul risultato quando ti serve un DataFrame completamente indipendente fin dall’inizio.

Errori e casi limite

Il *args nella firma invita a un’abitudine da NumPy, ma pandas scambia sempre i due assi di un DataFrame e non accetta alcuna permutazione degli assi:

import pandas as pd

dataframe = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
print(dataframe.transpose(1))

Produzione:

ValueError: the 'axes' parameter is not supported in the pandas implementation of transpose()

Anche una tupla come (1, 0) fallisce con lo stesso ValueError. Le forme degeneri, invece, sono input validi e non errori:

import pandas as pd

empty = pd.DataFrame(columns=["A", "B"])
print("Original shape:", empty.shape)
print("Transposed shape:", empty.transpose().shape)

single_row = pd.DataFrame({"A": [1], "B": [2], "C": [3]})
print(single_row.transpose())

Produzione:

Original shape: (0, 2)
Transposed shape: (2, 0)
   0
A  1
B  2
C  3

Un DataFrame con colonne ma senza righe scambia la forma (0, 2) con (2, 0), e una singola riga diventa una singola colonna il cui indice contiene le etichette delle colonne originali.