pandasのデータ型dtype一覧とastypeによる変換(キャスト)
pandas.Series
は一つのデータ型dtype
、pandas.DataFrame
は各列ごとにそれぞれデータ型dtype
を保持している。
dtype
は、コンストラクタで新たにオブジェクトを生成する際やcsvファイルなどから読み込む際に指定したり、astype()
メソッドで変換(キャスト)したりすることができる。
ここでは、
- pandasの主要なデータ型
dtype
一覧 object
型と文字列- 注意: 文字列メソッド
- 注意: 欠損値
NaN
astype()
によるデータ型dtype
の変換(キャスト)pandas.Series
のデータ型dtype
を変更pandas.DataFrame
全体のデータ型dtype
を一括で変更pandas.DataFrame
の任意の列のデータ型dtype
を個別に変更
- CSVファイル読み込み時のデータ型
dtype
指定- すべての列に同じデータ型を指定
- 列ごとにデータ型を指定
- 暗黙の型変換
について、サンプルコードとともに説明する。
NumPyのデータ型dtype
とastype()
については以下の記事を参照。
データ型dtype
によって列を抽出する方法は以下の記事を参照。
pandasの主要なデータ型dtype一覧
pandasの主要なデータ型dtype
は以下の通り。
データ型dtype |
型コード | 説明 |
---|---|---|
int8 |
i1 |
符号あり8ビット整数型 |
int16 |
i2 |
符号あり16ビット整数型 |
int32 |
i4 |
符号あり32ビット整数型 |
int64 |
i8 |
符号あり64ビット整数型 |
uint8 |
u1 |
符号なし8ビット整数型 |
uint16 |
u2 |
符号なし16ビット整数型 |
uint32 |
u4 |
符号なし32ビット整数型 |
uint64 |
u8 |
符号なし64ビット整数型 |
float16 |
f2 |
半精度浮動小数点型(符号部1ビット、指数部5ビット、仮数部10ビット) |
float32 |
f4 |
単精度浮動小数点型(符号部1ビット、指数部8ビット、仮数部23ビット) |
float64 |
f8 |
倍精度浮動小数点型(符号部1ビット、指数部11ビット、仮数部52ビット) |
float128 |
f16 |
四倍精度浮動小数点型(符号部1ビット、指数部15ビット、仮数部112ビット) |
complex64 |
c8 |
複素数(実部・虚部がそれぞれfloat32 ) |
complex128 |
c16 |
複素数(実部・虚部がそれぞれfloat64 ) |
complex256 |
c32 |
複素数(実部・虚部がそれぞれfloat128 ) |
bool |
? |
ブール型(True or False ) |
object |
O |
Pythonオブジェクト型 |
データ型名の末尾の数字はbit
で表し、型コード末尾の数字はbyte
で表す。同じ型でも値が違うので注意。
bool
型の型コード?
は不明という意味ではなく文字通り?
が割り当てられている。
日時を表すdatetime64
型については以下の記事を参照。
各種メソッドの引数でデータ型dtype
を指定するとき、例えばfloat64
型の場合は、
np.float64
- 文字列
'float64'
- 型コードの文字列
'f8'
のいずれでもOK。
import pandas as pd
import numpy as np
s = pd.Series([0, 1, 2], dtype=np.float64)
print(s.dtype)
# float64
s = pd.Series([0, 1, 2], dtype='float64')
print(s.dtype)
# float64
s = pd.Series([0, 1, 2], dtype='f8')
print(s.dtype)
# float64
ビット精度の数値を省略してint
やfloat
, str
のようなPythonの型で指定することもできる。
この場合、等価なdtype
に自動的に変換されるが、どのdtype
に変換されるかは環境(Python2かPython3か、32ビットか64ビットかなど)によって異なる。
以下の例はPython3、64ビット環境のもの。uint
はPythonの型ではないが便宜上まとめて挙げておく。
Pythonの型 | 等価なdtype の例 |
---|---|
int |
int64 |
float |
float64 |
str |
object (各要素がstr 型) |
(uint ) |
uint64 |
引数で指定する場合はint
やfloat
でも文字列'int'
, 'float'
でもOK。Pythonの型ではないuint
は文字列'uint'
のみ可。
s = pd.Series([0, 1, 2], dtype='float')
print(s.dtype)
# float64
s = pd.Series([0, 1, 2], dtype=float)
print(s.dtype)
# float64
s = pd.Series([0, 1, 2], dtype='uint')
print(s.dtype)
# uint64
整数、浮動小数点数においてそれぞれの型が取り得る値の範囲(最小値・最大値)はnp.iinfo()
, np.finfo()
で確認できる。詳細は以下の記事を参照。
なお、pandasのみをインポートしている場合でもpd.np.iinfo()
, pd.np.finfo()
のように使用できる。
文字列str
型とobject
型についての詳細は次に説明する。
object型と文字列
object
型は特殊なデータ型で、Pythonオブジェクトへのポインターを格納する。各要素のデータはそれぞれ別の型を持つ場合がある。
pandasでは文字列を含むSeries
やDataFrame
の列はobject
型となるが、各要素はそれぞれの型を持っており、すべての要素が文字列str
型とは限らない。
例を示す。
pd.np.nan
は欠損値を表す。NumPyをインポートしていればnp.nan
でもよい。
ここではmap()
メソッドで各要素に組み込み関数type()
を適用して型を確認している。
s_object = pd.Series([0, 0.1, 'abc', pd.np.nan])
print(s_object)
# 0 0
# 1 0.1
# 2 abc
# 3 NaN
# dtype: object
print(s_object.map(type))
# 0 <class 'int'>
# 1 <class 'float'>
# 2 <class 'str'>
# 3 <class 'float'>
# dtype: object
コンストラクタでdtype
にstr
を指定するか、後述のastype()
でstr
を指定すると、すべての要素がstr
型に変換される。(ファイルから読み取る場合については後述)
コンストラクタの場合。なお、これはpandas0.23.0の場合で、以前のバージョンではコンストラクタのdtype
による設定では数値型の要素が文字列str
型に変換されないことがあった。注意。
s_str_constructor = pd.Series([0, 0.1, 'abc', pd.np.nan], dtype=str)
print(s_str_constructor)
# 0 0
# 1 0.1
# 2 abc
# 3 nan
# dtype: object
print(s_str_constructor.map(type))
# 0 <class 'str'>
# 1 <class 'str'>
# 2 <class 'str'>
# 3 <class 'str'>
# dtype: object
astype()
の場合。
s_str_astype = s_object.astype(str)
print(s_str_astype)
# 0 0
# 1 0.1
# 2 abc
# 3 nan
# dtype: object
print(s_str_astype.map(type))
# 0 <class 'str'>
# 1 <class 'str'>
# 2 <class 'str'>
# 3 <class 'str'>
# dtype: object
注意: 文字列メソッド
dtype
が同じobject
型でも、要素の型によってstrアクセサによる文字列メソッドの結果が異なるので注意。
例えば文字列の文字数を返すstr.len()
を適用すると、str
型に変換されていない数値型の要素はNaN
を返す。
print(s_str_astype.str.len())
# 0 1
# 1 3
# 2 3
# 3 3
# dtype: int64
print(s_object.str.len())
# 0 NaN
# 1 NaN
# 2 3.0
# 3 NaN
# dtype: float64
このように文字列メソッドの結果にNaN
が含まれている場合は列のデータ型がobject
でも各要素がstr
型に変換されていない可能性がある。
文字列メソッドの前にastype(str)
を適用すればOK。
print(s_object.astype(str).str.len())
# 0 1
# 1 3
# 2 3
# 3 3
# dtype: int64
文字列メソッドの利用については以下の記事も参照。
注意: 欠損値NaN
これまでの例にもあるように、データ型object
の列の欠損値NaN
はfloat
型。
print(s_object)
# 0 0
# 1 0.1
# 2 abc
# 3 NaN
# dtype: object
print(s_object.map(type))
# 0 <class 'int'>
# 1 <class 'float'>
# 2 <class 'str'>
# 3 <class 'float'>
# dtype: object
欠損値はisnull()
で判定したり、dropna()
で削除したりできる。
print(s_object.isnull())
# 0 False
# 1 False
# 2 False
# 3 True
# dtype: bool
print(s_object.dropna())
# 0 0
# 1 0.1
# 2 abc
# dtype: object
文字列str
にキャストすると欠損値も文字列'nan'
となる。
print(s_str_astype)
# 0 0
# 1 0.1
# 2 abc
# 3 nan
# dtype: object
print(s_str_astype.map(type))
# 0 <class 'str'>
# 1 <class 'str'>
# 2 <class 'str'>
# 3 <class 'str'>
# dtype: object
文字列'nan'
は欠損値を処理するメソッドの対象とならない。
print(s_str_astype.isnull())
# 0 False
# 1 False
# 2 False
# 3 False
# dtype: bool
print(s_str_astype.dropna())
# 0 0
# 1 0.1
# 2 abc
# 3 nan
# dtype: object
キャストする前に欠損値の処理を行うか、replace()
で文字列'nan'
を欠損値に置き換えればOK。
s_str_astype_nan = s_str_astype.replace('nan', pd.np.nan)
print(s_str_astype_nan)
# 0 0
# 1 0.1
# 2 abc
# 3 NaN
# dtype: object
print(s_str_astype_nan.map(type))
# 0 <class 'str'>
# 1 <class 'str'>
# 2 <class 'str'>
# 3 <class 'float'>
# dtype: object
print(s_str_astype_nan.isnull())
# 0 False
# 1 False
# 2 False
# 3 True
# dtype: bool
astype()によるデータ型dtypeの変換(キャスト)
pandas.DataFrame
, pandas.Series
のメソッドastype()
を使うとデータ型dtype
を変更できる。
astype()
はデータ型dtype
が変更された新たなpandas.Series
またはpandas.DataFrame
を返し、元のオブジェクトは変更されない。
例として以下のデータを使用する。
import pandas as pd
df = pd.read_csv('data/src/sample_header.csv')
print(df)
# a b c d
# 0 11 12 13 14
# 1 21 22 23 24
# 2 31 32 33 34
s = df['c']
print(s)
# 0 13
# 1 23
# 2 33
# Name: c, dtype: int64
サンプルのcsvファイルはコチラ。
pandas.Seriesのデータ型dtypeを変更
pandas.Series
のメソッドastype()
の引数にデータ型dtype
を指定すると、そのdtype
に変更された新たなpandas.Series
が返される。元のpandas.Series
はそのままで変換されない。
s_f = s.astype('float64')
print(s_f)
# 0 13.0
# 1 23.0
# 2 33.0
# Name: c, dtype: float64
print(s)
# 0 13
# 1 23
# 2 33
# Name: c, dtype: int64
上述のようにdtype
は様々な形で指定できる。
s_f = s.astype('float')
print(s_f.dtype)
# float64
s_f = s.astype(float)
print(s_f.dtype)
# float64
s_f = s.astype('f8')
print(s_f.dtype)
# float64
文字列に変換したい場合はstr
(または'str'
)を指定する。object
を指定した場合はstr
には変換されない。Series
としては同じobject
型でも中身の型が異なる場合があるので注意。
s_s = s.astype(str)
print(s_s)
# 0 13
# 1 23
# 2 33
# Name: c, dtype: object
print(s_s.map(type))
# 0 <class 'str'>
# 1 <class 'str'>
# 2 <class 'str'>
# Name: c, dtype: object
s_o = s.astype('object')
print(s_o)
# 0 13
# 1 23
# 2 33
# Name: c, dtype: object
print(s_o.map(type))
# 0 <class 'int'>
# 1 <class 'int'>
# 2 <class 'int'>
# Name: c, dtype: object
pandas.DataFrame全体のデータ型dtypeを一括で変更
pandas.DataFrame
は列ごとにデータ型dtype
を保持している。
それぞれのdtype
はdtypes
属性で取得・確認できる。
print(df)
# a b c d
# 0 11 12 13 14
# 1 21 22 23 24
# 2 31 32 33 34
print(df.dtypes)
# a int64
# b int64
# c int64
# d int64
# dtype: object
pandas.DataFrame
のメソッドastype()
の引数にデータ型dtype
を指定すると、すべての列のdtype
が変更された新たなpandas.DataFrame
が返される。
df_f = df.astype('float64')
print(df_f)
# a b c d
# 0 11.0 12.0 13.0 14.0
# 1 21.0 22.0 23.0 24.0
# 2 31.0 32.0 33.0 34.0
print(df_f.dtypes)
# a float64
# b float64
# c float64
# d float64
# dtype: object
pandas.DataFrameの任意の列のデータ型dtypeを個別に変更
astype()
の引数に{列名: データ型}
の辞書を指定すると、任意の列のデータ型dtype
を個別に変更できる。
一列だけでも複数列でも指定可能。
df_fcol = df.astype({'a': float})
print(df_fcol)
# a b c d
# 0 11.0 12 13 14
# 1 21.0 22 23 24
# 2 31.0 32 33 34
print(df_fcol.dtypes)
# a float64
# b int64
# c int64
# d int64
# dtype: object
df_fcol2 = df.astype({'a': 'float32', 'c': 'int8'})
print(df_fcol2)
# a b c d
# 0 11.0 12 13 14
# 1 21.0 22 23 24
# 2 31.0 32 33 34
print(df_fcol2.dtypes)
# a float32
# b int64
# c int8
# d int64
# dtype: object
CSVファイル読み込み時のデータ型dtype指定
pandasでは関数read_csv()
でCSVファイルを読み込むことができる。
読み込み時に引数dtype
で任意の型を指定できる。
サンプルのCSVファイルはコチラ。
,a,b,c,d
ONE,1,"001",100,x
TWO,2,"020",,y
THREE,3,"300",300,z
引数dtype
を省略すると、列ごとに最適なdtype
が自動的に選ばれる。
import pandas as pd
df = pd.read_csv('data/src/sample_header_index_dtype.csv', index_col=0)
print(df)
# a b c d
# ONE 1 1 100.0 x
# TWO 2 20 NaN y
# THREE 3 300 300.0 z
print(df.dtypes)
# a int64
# b int64
# c float64
# d object
# dtype: object
print(df.applymap(type))
# a b c d
# ONE <class 'int'> <class 'int'> <class 'float'> <class 'str'>
# TWO <class 'int'> <class 'int'> <class 'float'> <class 'str'>
# THREE <class 'int'> <class 'int'> <class 'float'> <class 'str'>
すべての列に同じデータ型を指定
引数dtype
に任意のデータ型を指定するとすべての列が変換される。
dtype=str
でもdtype=object
でも各要素がstr
型に変換される。欠損値NaN
はstr
型に変換されない。
dtype=str
の場合。
df_str = pd.read_csv('data/src/sample_header_index_dtype.csv',
index_col=0, dtype=str)
print(df_str)
# a b c d
# ONE 1 001 100 x
# TWO 2 020 NaN y
# THREE 3 300 300 z
print(df_str.dtypes)
# a object
# b object
# c object
# d object
# dtype: object
print(df_str.applymap(type))
# a b c d
# ONE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
# TWO <class 'str'> <class 'str'> <class 'float'> <class 'str'>
# THREE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
dtype=object
の場合。
df_object = pd.read_csv('data/src/sample_header_index_dtype.csv',
index_col=0, dtype=object)
print(df_object)
# a b c d
# ONE 1 001 100 x
# TWO 2 020 NaN y
# THREE 3 300 300 z
print(df_object.dtypes)
# a object
# b object
# c object
# d object
# dtype: object
print(df_object.applymap(type))
# a b c d
# ONE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
# TWO <class 'str'> <class 'str'> <class 'float'> <class 'str'>
# THREE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
読み込み後にastype()
でstr
にキャストした場合は欠損値も文字列'nan'
に変換されるので注意。
print(df.astype(str).applymap(type))
# a b c d
# ONE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
# TWO <class 'str'> <class 'str'> <class 'str'> <class 'str'>
# THREE <class 'str'> <class 'str'> <class 'str'> <class 'str'>
列ごとにデータ型を指定
astype()
と同様に、辞書形式で列ごとに指定することもできる。
列名だけでなく列番号でも指定できる。インデックス列を指定している場合、インデックス列も含めた列番号で指定する必要があるので注意。
df_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
index_col=0, dtype={'a': float, 'b': str})
print(df_col)
# a b c d
# ONE 1.0 001 100.0 x
# TWO 2.0 020 NaN y
# THREE 3.0 300 300.0 z
print(df_col.dtypes)
# a float64
# b object
# c float64
# d object
# dtype: object
df_col = pd.read_csv('data/src/sample_header_index_dtype.csv',
index_col=0, dtype={1: float, 2: str})
print(df_col)
# a b c d
# ONE 1.0 001 100.0 x
# TWO 2.0 020 NaN y
# THREE 3.0 300 300.0 z
print(df_col.dtypes)
# a float64
# b object
# c float64
# d object
# dtype: object
暗黙の型変換
astype()
による明示的な型変換だけでなく、演算によって暗黙の型変換が行われる場合がある。
整数int
の列と浮動小数点数float
の列を持つpandas.DataFrame
を例とする。
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
例えば、int
の列とfloat
の列との+
演算子による加算の結果はfloat
となる。
print(df_mix['col_int'] + df_mix['col_float'])
# A 0.1
# B 1.2
# C 2.3
# dtype: float64
スカラー値との演算でも同様に暗黙の型変換が行われる。/
演算子による除算の結果はfloat
。
print(df_mix / 1)
# col_int col_float
# A 0.0 0.1
# B 1.0 0.2
# C 2.0 0.3
print((df_mix / 1).dtypes)
# col_int float64
# col_float float64
# dtype: object
+
, -
, *
, //
, **
では、整数int
同士の場合はint
、浮動小数点数float
が含まれる場合はfloat
となる。
print(df_mix * 1)
# col_int col_float
# A 0 0.1
# B 1 0.2
# C 2 0.3
print((df_mix * 1).dtypes)
# col_int int64
# col_float float64
# dtype: object
print(df_mix * 1.0)
# col_int col_float
# A 0.0 0.1
# B 1.0 0.2
# C 2.0 0.3
print((df_mix * 1.0).dtypes)
# col_int float64
# col_float float64
# dtype: object
NumPy配列ndarray
の暗黙の型変換に準ずる。
上の例のような演算のほか、loc
やiloc
で1行をpandas.Series
として取得したり、T
やtranspose()
で転置を行ったりする際にも型変換が行われる場合がある。
print(df_mix.loc['A'])
# col_int 0.0
# col_float 0.1
# Name: A, dtype: float64
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
これは、行取得や転置などの処理の結果、複数の型の要素が混在する列やpandas.Series
が生じてしまうのが原因。pandas.Series
およびpandas.DataFrame
の各列は単一のデータ型dtype
でなければならないので、型変換が発生する。
詳細は以下の記事を参照。
なお、要素への値の代入ではpandas.DataFrame
の列やpandas.Series
の型変換は行われない。代入された値のほうの型が変わる。
例えば、整数int
の列に浮動小数点数float
の値を代入しても、列のデータ型はint
のまま。代入した値は小数点以下切り捨てされてint
に変換される。float
の列にint
の値を代入する場合も、列の型はそのままで値のほうがfloat
に変換される。
df_mix.at['A', 'col_int'] = 10.9
df_mix.at['A', 'col_float'] = 10
print(df_mix)
# col_int col_float
# A 10 10.0
# B 1 0.2
# C 2 0.3
print(df_mix.dtypes)
# col_int int64
# col_float float64
# dtype: object
列の型に変換できない値を代入しようとするとエラーとなる。
# df_mix.at['A', 'col_int'] = 'abc'
# ValueError: invalid literal for int() with base 10: 'abc'