note.nkmk.me

pandasのデータ型dtype一覧とastypeによる変換(キャスト)

Date: 2018-03-11 / Modified: 2018-06-12 / tags: Python, pandas

pandas.Seriesは一つのデータ型dtypepanas.DataFrameは各列ごとにそれぞれデータ型dtypeを保持している。

dtypeは、コンストラクタで新たにオブジェクトを生成する際やcsvファイルなどから読み込む際に指定したり、astype()メソッドで変換(キャスト)したりすることができる。

ここでは、

  • pandasの主要なデータ型dtype一覧
  • object型と文字列
  • astype()によるデータ型dtypeの変換(キャスト)
    • pandas.Seriesのデータ型dtypeを変更
    • pandas.DataFrame全体のデータ型dtypeを一括で変更
    • pandas.DataFrameの任意の列のデータ型dtypeを個別に変更
  • csvファイル読み込み時のデータ型dtype指定

について、サンプルコードとともに説明する。

NumPyのデータ型dtypeastype()については以下の記事を参照。

データ型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

ビット精度の数値を省略してintfloat, strのようなPythonの型で指定することもできる。

この場合、等価なdtypeに自動的に変換されるが、どのdtypeに変換されるかは環境(Python2かPython3か、32ビットか64ビットかなど)によって異なる。

以下の例はPython3、64ビット環境のもの。uintはPythonの型ではないが便宜上まとめて挙げておく。

Pythonの型 等価なdtypeの例
int int64
float float64
str object(各要素がstr型)
uint uint64

引数で指定する場合はintfloatでも文字列'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

文字列str型とobject型については次に説明する。

object型と文字列

object型は特殊なデータ型で、Pythonオブジェクトへのポインターを格納する。各要素のデータはそれぞれ別の型を持つ場合がある。

pandasでは文字列を含むSeriesDataFrameの列は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

コンストラクタでdtypestrを指定するか、後述の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の列の欠損値NaNfloat型。

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を保持している。

それぞれのdtypedtypes属性で取得・確認できる。

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型に変換される。欠損値NaNstr型に変換されない。

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
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事