LoginSignup
0
1

More than 1 year has passed since last update.

Pandas/PythonのDataFrameで出てくるデータ型と型変換

Posted at

はじめに

PandasのDFでデータを扱うとき。最初はあまり意識しないが、すぐにデータ型という概念にぶつかる。
というのも、例えばread_csv等でデータを読み込む際、pandas側でいいように型を設定してくれるのだが、
ふとした拍子で意外な型になっており、そのデータを扱う際にエラーになったりすることがある。

なのでデータ型の変更や、データ型毎の代表的な処理をまとめてみた。

存在するデータ型

pandasのdocにきれいにまとまっていればいいのだけれど、見当たらず。
以下以外にもあるようだが、主要どころを理解するという意味では以下を理解すればよさそう。

用途 Pandas Python
文字列
複数データ混合
object (内容による)
整数 int64 int
浮動小数 float64 float
真/偽 bool bool
日付、時刻 datetime64 -
2つの時刻の差 timedelta[ns] -
カテゴリ category -

上記以外にも、pandasの型として以下のようなものもある。
必要な時が来たら追加で整理したい。

  • int8、int16、int32:それぞれ末尾の数字=ビット数 ※int以外にも同様の概念あり
  • unit64:int64と同様に整数だが、unit64の場合符号なし。
  • complex128:複素数。実部と虚部がそれぞれfloat64で、全体として128
  • category:カテゴリデータ。性別を0や1で示すような、「数値+NaN」で扱うが、足し算引き算等をする意味のない値。int64と明確に区別するとき定義する
  • string:文字列。厄介なことに昔のpandasにはなく、Ver1.0から導入されたらしい。
        後方互換のためread時にはobject形で読み込まれるため、string型を意識的に使う人が少ない。

pandasのString型については以下記載あり。
objectでなく最初からStringで実装していればよかったなという雰囲気を感じる、、

実験用データの定義

Python
import pandas as pd
import numpy as np

df = pd.DataFrame({"index":[0, 1, 2, 3],
                   "id":[1, 2, 3, 4],
                   "F-Name":['aa', 'bb', 'cc', 'dd'],
                   "L-Name":['AA', 'BB', 'CC', 'DD'],
                   "point1":[63, 37, 20, 90],
                   "point2":[31, 41, 66, np.nan],
                   "height":[165.3, 143.2, 174.2, 158.0],
                   "weight":[51, 47, 65, 56],
                   "sex":[1, 0, 1, 9],
                   "birth":['1992-12-01', '1995-03-20', '1986-10-09', '1998-07-14'],
                   "add_date":['2018年5月3日', '2019年10月18日', '2020年1月17日', '2021年9月13日'],
                   "upd_date":[20210103, 20210304, 20220404, 20211225],
                   "active":[True, False, True, True]}).set_index("index")

# 		id	F-Name	L-Name	point1	point2	height	weight	sex	birth		add_date		upd_date	active
# index										
# 0		1	aa		AA		63		31.0	165.3	51		1	1992-12-01	2018年5月3日		20210103	True
# 1		2	bb		BB		37		41.0	143.2	47		0	1995-03-20	2019年10月18日	20210304	False
# 2		3	cc		CC		20		66.0	174.2	65		1	1986-10-09	2020年1月17日	20220404	True
# 3		4	dd		DD		90		NaN		158.0	56		9	1998-07-14	2021年9月13日	20211225	True

データ型の表示:dtypes

Python
df.dtypes

# id            int64
# F-Name       object
# L-Name       object
# point1        int64
# point2      float64
# height      float64
# sex           int64
# birth        object
# add_date     object
# upd_date      int64
# active         bool
# dtype: object
  • 整数はint64、文字列はobject、小数はfloat64、真偽はboolとなる
  • NaNはpythonではfloatのみ、intでは存在しない概念のため、整数の中にNaNが含まれるとその列はfloat64になる
  • 日付型も最初はobject(文字列)
  • 意図する型と必ずしも一致しないケースがあり得る(例:weightはたまたま整数しかなかったからint64となっているが、本来小数も許容してほしい)
  • 上記ではないが、一見数字でも、文字列として元データが定義していると、objectとして取り込まれることがある

データ型の変換:astype

Python
# pandasの型名称で指定する場合は''で囲う
# pythonの型名称で指定する場合は''が不要
df = df.astype({'point1': float, 'weight': 'float64', 'sex': 'category'}) 
df.dtypes

# id             int64
# F-Name        object
# L-Name        object
# point1       float64
# point2       float64
# height       float64
# weight       float64
# sex         category
# birth         object
# add_date      object
# upd_date       int64
# active          bool
# dtype: object

データ型の変換(日付):to_datetime

Python
df['birth'] = pd.to_datetime(df['birth'])
  • to_datetimeで変換できる日付文字列は以下

    • 日付
    表記法
    区切りなし(※) 20230228
    ハイフン 2023-02-28
    スラッシュ 2023/02/28
    MM-DD-YYYY 02-28-2023

    区切りなしは扱いに注意。単に8文字の数字が並んだ文字列をto_datetimeにかけると、ミリ秒として処理される
    結果、「1970-01-01 00:00:00.020210103」みたいな表記となってしまう。
    これを回避する場合以下表記が必要

    Python
    # to_datetimeは文字列に対する処理のため、int64をobjectに変換
    df = df.astype({'upd_date': 'object'}) 
    # ミリ秒として扱われないように、formatで形式を指定
    df['upd_date']  = pd.to_datetime(df['upd_date'], format='%Y%m%d')
    
  • to_datetimeで変換できる日付時刻文字列は以下

    • 日付+時刻
      日付部は上記の表の形式であればどれでも可
      以下は区切りなしケースで例を記載
      MM、SS部分を記載しない場合、00で補完される
    表記法
    日付T時刻 20230228T14:21:31
    日付(スペース)時刻 20230228 14:21:31
    AM、PM付き 20230228 02:21:31 PM
    20230228T02:21:31 PM
    20230228 02:21:31 AM
    20230228T02:21:31 PM
    時刻区切りなし 20230228T142131

to_datetimeで変換できない形式の文字列は、formatを用いて変換を行う

Python
df["add_date"] = pd.to_datetime(df["add_date"], format="%Y年%m月%d日")

formatで指定できるコードは以下の通り
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

よく使うものを抜粋

フォーマットコード 指定内容
%Y 4桁の年 2023
%m 2桁の月 02
%d 2桁の日 28
%H 時間(24時間) 13
%M 26
%S 49
%y 2桁の年 23
%B 英語月 February
%b 英語月(短縮) Feb
%X HH:MM:SS 13:26:49
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1