pandas: Transpose DataFrame (swap rows and columns)
The T
attribute or the transpose()
method allows you to swap (= transpose) the rows and columns of pandas.DataFrame
.
Neither method updates the original object; instead, they return a new transposed object.
Note that depending on the data type (dtype
) of each column, a view is created instead of a copy. Consequently, if you change either the original or the transposed object, the other will also be affected.
Refer to the following articles for transposing numpy.ndarray
or a two-dimensional list
(list of lists).
- NumPy: Transpose ndarray (swap rows and columns, rearrange axes)
- Transpose 2D list in Python (swap rows and columns)
The sample code in this article uses pandas version 2.0.3
.
import pandas as pd
print(pd.__version__)
# 2.0.3
Transpose pandas.DataFrame
using the T
attribute
The T
attribute of DataFrame
returns the transposed object.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
print(df.T)
# A B C
# X 0 1 2
# Y 3 4 5
Transpose pandas.DataFrame
using the transpose()
method
You can transpose DataFrame
using the transpose()
method.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
print(df.transpose())
# A B C
# X 0 1 2
# Y 3 4 5
Update the original object itself
The transpose()
method does not provide an argument like inplace
to modify the original object directly. You can assign it to the original object itself.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
df = df.T
print(df)
# A B C
# X 0 1 2
# Y 3 4 5
Type conversion during transposition
The DataFrame
has a data type (dtype
) for each column.
If all columns have the same data type, the data type remains the same even if transposed with T
or transpose()
.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
print(df.dtypes)
# X int64
# Y int64
# dtype: object
print(df.T)
# A B C
# X 0 1 2
# Y 3 4 5
print(df.T.dtypes)
# A int64
# B int64
# C int64
# dtype: object
If each column has a different data type, the type is converted. For example, if a column contains both an integer (int
) and a floating-point number (float
), the data type of the column is float
.
df_mix = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.1, 0.2, 0.3]}, index=['A', 'B', 'C'])
print(df_mix)
# col_int col_float
# A 0 0.1
# B 1 0.2
# C 2 0.3
print(df_mix.dtypes)
# col_int int64
# col_float float64
# dtype: object
print(df_mix.T)
# A B C
# col_int 0.0 1.0 2.0
# col_float 0.1 0.2 0.3
print(df_mix.T.dtypes)
# A float64
# B float64
# C float64
# dtype: object
It will not be restored if it is transposed again. You should apply astype()
to cast the data type.
print(df_mix.T.T)
# col_int col_float
# A 0.0 0.1
# B 1.0 0.2
# C 2.0 0.3
print(df_mix.T.T.dtypes)
# col_int float64
# col_float float64
# dtype: object
The data type of a column containing the string (str
) is object
.
df_mix2 = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.1, 0.2, 0.3], 'col_str': ['a', 'b', 'c']},
index=['A', 'B', 'C'])
print(df_mix2)
# col_int col_float col_str
# A 0 0.1 a
# B 1 0.2 b
# C 2 0.3 c
print(df_mix2.dtypes)
# col_int int64
# col_float float64
# col_str object
# dtype: object
print(df_mix2.T)
# A B C
# col_int 0 1 2
# col_float 0.1 0.2 0.3
# col_str a b c
print(df_mix2.T.dtypes)
# A object
# B object
# C object
# dtype: object
print(df_mix2.T.T)
# col_int col_float col_str
# A 0 0.1 a
# B 1 0.2 b
# C 2 0.3 c
print(df_mix2.T.T.dtypes)
# col_int object
# col_float object
# col_str object
# dtype: object
Views and copies during transposition
If all columns have the same data type, T
or transpose()
returns a view. Since the original and the view objects share memory, changing one element will change the other.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
df_T = df.T
print(df_T)
# A B C
# X 0 1 2
# Y 3 4 5
df_transpose = df.transpose()
print(df_transpose)
# A B C
# X 0 1 2
# Y 3 4 5
df.at['A', 'X'] = 100
print(df)
# X Y
# A 100 3
# B 1 4
# C 2 5
print(df_T)
# A B C
# X 100 1 2
# Y 3 4 5
print(df_transpose)
# A B C
# X 100 1 2
# Y 3 4 5
If the data type (dtype
) is different for each column, T
and transpose()
create a copy. Since the transposed object allocates a new memory area, if one is changed, the other remains unchanged.
df_mix = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.1, 0.2, 0.3]}, index=['A', 'B', 'C'])
print(df_mix)
# col_int col_float
# A 0 0.1
# B 1 0.2
# C 2 0.3
df_mix_T = df_mix.T
print(df_mix_T)
# A B C
# col_int 0.0 1.0 2.0
# col_float 0.1 0.2 0.3
df_mix_transpose = df_mix.transpose()
print(df_mix_transpose)
# A B C
# col_int 0.0 1.0 2.0
# col_float 0.1 0.2 0.3
df_mix.at['A', 'col_int'] = 100
print(df_mix)
# col_int col_float
# A 100 0.1
# B 1 0.2
# C 2 0.3
print(df_mix_T)
# A B C
# col_int 0.0 1.0 2.0
# col_float 0.1 0.2 0.3
print(df_mix_transpose)
# A B C
# col_int 0.0 1.0 2.0
# col_float 0.1 0.2 0.3
If you wish to create a copy even when all columns have the same data type, use the copy()
method on T
. For transpose()
, set the copy
argument to True
.
df = pd.DataFrame({'X': [0, 1, 2], 'Y': [3, 4, 5]}, index=['A', 'B', 'C'])
print(df)
# X Y
# A 0 3
# B 1 4
# C 2 5
df_T_copy = df.T.copy()
print(df_T_copy)
# A B C
# X 0 1 2
# Y 3 4 5
df_transpose_copy = df.transpose(copy=True)
print(df_transpose_copy)
# A B C
# X 0 1 2
# Y 3 4 5
df.at['A', 'X'] = 100
print(df)
# X Y
# A 100 3
# B 1 4
# C 2 5
print(df_T_copy)
# A B C
# X 0 1 2
# Y 3 4 5
print(df_transpose_copy)
# A B C
# X 0 1 2
# Y 3 4 5
In transpose()
, the default for copy
is False
, which creates a view instead of a copy if possible. If the data type is different for each column, as in the example above, a copy is created even if copy=False
.