Python – 4-5. pandas(DataFrame)Date
5. 日付操作
pandasにおける日付型についての理解
dataframeでは、日付型項目をあくまでもobject型として保持している。
dtypesメソッドで全列の型を確認(hiredate列に注目)
df_emp.dtypes empno int64 ename object job object manager float64 hiredate object ※ sal int64 comm float64 dept float64 dtype: object
列単体としてはSeries型であることを確認
type(df_emp['hiredate']) → <class 'pandas.core.series.Series'>
このSeriesのdtypeを取ると、「O」となっている。
df_emp['hiredate'].dtype dtype('O')
empnoだと「int64」というデータ型らしき値が戻る
df_emp['empno'].dtype → dtype('int64')
行・列を指定した、empno=7369(index=0)の要素 hiredate=1980/12/17 単体のデータ型は、、、
df_emp.loc[0,'hiredate'].dtype → AttributeError: 'str' object has no attribute 'dtype'
エラーになってしまう。
empnoだと、この方法でも「int64」が取れる
df_emp.loc[0,'empno'].dtype → dtype('int64')
type()を取ってみると、
type(df_emp.loc[0,'hiredate']) → <class 'str'>
⇒文字列
pd.to_datetime で明示的にdatetime/Timestamp型に変換する
pd.to_datetime(df_emp['hiredate']) 0 1980-12-17 : 14 1985-03-17 Name: hiredate, dtype: datetime64[ns] pd.to_datetime(df_emp.loc[0,'hiredate']) Timestamp('1980-12-17 00:00:00')
読込時、データ型にdatetime64型を指定することもできる。
(parse_dates=[4]で5番目の列を日付型として解析させている)
df_emp = pd.read_csv('emp.csv', encoding='utf-8', parse_dates=[4]) # データ型を確認(dtype) df_emp['hiredate'].dtype >> dtype('<M8[ns]') # データ型を確認(type) type(df_emp.loc[0,'hiredate']) >> <class 'pandas._libs.tslibs.timestamps.Timestamp'>
文字列による期間指定での抽出(1)
hiredateが 1981/5/1 以降を抽出
SQL
SELECT * FROM emp WHERE hiredate >= TO_DATE('1981/05/01','YYYY/MM/DD')
pandas
df_emp.query('hiredate >= "1981/05/01"')
文字列による期間指定での抽出(2)
hiredateが 1981/5/1 以降、1981/12/3より前を抽出
SQL
SELECT * FROM emp WHERE hiredate >= TO_DATE('1981/05/01','YYYY/MM/DD') AND hiredate < TO_DATE('1981/12/03','YYYY/MM/DD')
pandas
df_emp.query('hiredate >= "1981/05/01" and hiredate < "1981/12/03"')
dtアクセサを使用し、年を条件に抽出
SQL
SELECT * FROM emp WHERE TO_CHAR(hiredate, 'YYYY') = '1985'
pandas
df_emp[pd.to_datetime(df_emp.loc[:,'hiredate']).dt.year == 1985]
dtアクセサを使用した月を条件にした抽出
SQL
SELECT * FROM emp WHERE TO_CHAR(hiredate, 'MM') = '4'
pandas
df_emp[pd.to_datetime(df_emp.loc[:,'hiredate']).dt.month == 4]
dtアクセサを使用した日を条件にした抽出
SQL
SELECT * FROM emp WHERE TO_CHAR(hiredate, 'DD') = '17'
pandas
df_emp[pd.to_datetime(df_emp.loc[:,'hiredate']).dt.day == 17]
dtアクセサを使用した曜日を条件にした抽出
SQL
SELECT * FROM emp WHERE TO_CHAR(hiredate, 'D') = 1 ※ 1:日曜日~7:土曜日
pandas
df_emp[pd.to_datetime(df_emp.loc[:,'hiredate']).dt.dayofweek == 1] ※Monday=0, Sunday=6 ※isoweekday() を使うと、Monday=1, Sunday=7
dtアクセサを使用して、その月の日数を取得
SQL
SELECT emp, TO_CHAR(LASTDAY(hiredate), 'DD') FROM emp
pandas
pd.to_datetime(df_emp.loc[:,'hiredate']).dt.daysinmonth
dtアクセサを使用して、その月の1日の日付を取得
SQL
SELECT emp, TRUNC(hiredate, 'Day') FROM emp;
pandas
pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('D') # ==> OK 日付以外は固定的な頻度を表す周期パラメータを指定可能 pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('H') # ==> OK(時) pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('T') # ==> OK(分) pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('S') # ==> OK(秒) ※以下は、エラーになってしまう。 pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('MS') # ==> ng(月の開始) pd.to_datetime(df_emp.loc[:,'hiredate']).dt.round('Y') # ==> ng(年)
日付の引き算(社員Aのhiredate-社員Bのhiredate)
SQL
SELECT emp1.hiredate - emp0.hiredate FROM (SELECT ,empno, hiredate FROM emp WHERE empno = 7499) as emp1 ,(SELECT ,empno, hiredate FROM emp WHERE empno = 7369) as emp0
pandas
pd.to_datetime(df_emp.loc[1,'hiredate'])-pd.to_datetime(df_emp.loc[0,'hiredate'])
日付の計算(1日加算)
SQL
SELECT hiredate + 1 FROM emp;
pandas
datetime.timedeltaを使用する。days=1を指定して「1日間」を表す。
import datetime as dt diffdate = dt.timedelta(days=1) pd.to_datetime(df_emp.loc[:,'hiredate']) + diffdate
日付の計算(1ヶ月加算)
SQL
SELECT ADD_MONTHS(hiredate, 1) FROM emp;
pandas
from dateutil import relativedelta diffdate = relativedelta.relativedelta(months=1) pd.to_datetime(df_emp.loc[:,'hiredate']).apply(lambda x: x + diffdate)
<< 参考サイト >>
・Python で前月同日・前月末日を求める
https://blaue-fuchs.hatenadiary.org/entry/20110814/1313310157
・Pythonで日付の加算、特にnヶ月後やn年後の日付を求める方法
https://analytics-note.xyz/programming/relativedelta/
日付の計算(当月1日)
SQL
SELECT TRUNC(hiredate, 'MONTHS') FROM emp;
pandas
pd.to_datetime(df_emp.loc[:,'hiredate']).apply(lambda x: x.replace(day=1))
日付の計算(月末)
SQL
SELECT LASTDAY(hiredate) FROM emp;
pandas
dateutil.relativedelta を使用する。
※翌月同日を算出し、その月の1日を取得。更にその前日を算出する。 from dateutil import relativedelta addmonth1 = relativedelta.relativedelta(months=1) diffdate = relativedelta.relativedelta(days=1) pd.to_datetime(df_emp.loc[:,'hiredate']) \ .apply(lambda x:(x+addmonth1).replace(day=1) - diffdate)
日付の計算(年末)
SQL
SELECT TRUNC(ADD_MONTHS(hiredate, 12), 'YEAR')-1 FROM emp;
pandas
※翌年同日を算出し、その年の1月1日に置換。更にその前日を算出する。 from dateutil import relativedelta addmonth12 = relativedelta.relativedelta(years=1) diffdate = relativedelta.relativedelta(days=1) pd.to_datetime(df_emp.loc[:,'hiredate']) \ .apply(lambda x: (x + addmonth12) \ .replace(month=1).replace(day=1)-diffdate) ※別の方式。当月1日に変換し、それに13-月数を加算して、翌年1月1日を算出。その前日で年末を求める。 pd.to_datetime(df_emp.loc[:,'hiredate']) \ .apply(lambda x: x.replace(day=1) \ + relativedelta.relativedelta(months=13-x.month)-diffdate)
strftime() で文字列型に変換
SQL
SELECT emp, TO_CHAR(hiredate, 'YYYY-MM-DD') FROM emp;
pandas
pd.to_datetime(df_emp.loc[:,'hiredate']).dt.strftime('%Y-%m-%d') pd.to_datetime(df_emp.loc[:,'hiredate']).dt.strftime('%Y // %m // %d //') pd.to_datetime(df_emp.loc[:,'hiredate']).dt.strftime('%Y年%m月%d日') ## ↓年月日の表示が上手くいかない場合(Windows) pd.to_datetime(df_emp.loc[:,'hiredate']).dt.strftime('%Y年%m月%d日'.encode('unicode-escape').decode()) \ .str.encode('cp932').str.decode("unicode-escape")
※ Windows環境での注意事項
Windowsの場合は、書式文字列に年月日等のマルチバイト文字列を使用した場合に、
UnicodeEncodeError: 'locale’ codec can’t encode character '\u5e74’
が出る場合があります(’\u5e74’は「年」の文字コード表示)。
下記のような対応で解決する場合がありますが、詳細は環境等々の状況により異なりますので個別に確認ください。
chcp 65001 # Windowsの場合にコンソールのエンコーディングを指定する(戻すときはchcp 932) python -X utf8 # python起動時にコンソールの文字コードを指定 import datetime as dt import locale # localeモジュールで時間のロケールを'ja_JP.UTF-8'に変更する locale.setlocale(locale.LC_TIME, 'ja_JP.UTF-8') d = dt.date(2022, 12, 31) print(d.strftime('%A')) # => '土曜日' print(d.strftime('%Y年%m月%d日')) # ==> 2022年12月31日 # これでもダメな場合は、 print(d.strftime('%Y年%m月%d日'.encode('unicode-escape').decode()).encode().decode("unicode-escape"))
<< 参考サイト >>
【Python】曜日を取得する(英語&日本語)
https://qiita.com/_masa_u/items/e104d42bd6f200d3b959
Windows 上の Python で UTF-8 をデフォルトにする
https://qiita.com/methane/items/9a19ddf615089b071e71
最近のコメント