Pandas Series.dt.day 属性
Series.dt.dayPandas で日付時刻から日(日付)を抽出するために使用される属性です。これは dt アクセサの一部で、datetime 型の Series から月の第何日目(1〜31)をすばやく抽出できます。
時系列データ分析では、日単位での分析は一般的なニーズです。例えば、毎月の特定の日を分析したり、周期的なパターンを識別したりします。dt.dayこの属性により、このような操作は簡単かつ効率的になります。
単語の意味: day「日」を意味し、日付の中の日(月の第何日目)を返します。
基本構文とパラメータ
Series.dt.daySeries の dt アクセサの属性で、日を抽出するために使用します。
構文形式
Series.dt.day
パラメータの説明
この属性はパラメータを一切必要とせず、datetime Series の日情報に直接アクセスします。
戻り値の説明
- 戻り値:日(1〜31)を含む整数 Series を返します。
- 効果:datetime64 型の Series から日付の日の部分を抽出し、1 から 31 の整数を返します。
実例
簡単なものから複雑なものまでの一連の例を通して、Series.dt.dayの使い方を徹底的にマスターしましょう。
例1:基本の使い方 - 日の抽出
実例
import pandas as pd
# 1. 日時の Series を作成
print("=== 日時 Series の作成 ===")
dates = pd.Series([
'2023-01-15',
'2023-02-20',
'2023-03-05',
'2023-04-30',
'2023-05-25',
'2023-12-31'
])
# datetime 型に変換
datetime_series = pd.to_datetime(dates)
print("元の日付:")
print(datetime_series)
# 2. dt.day を使用して日を抽出
print("n=== dt.day を使用して日を抽出 ===")
days = datetime_series.dt.day
print("日:")
print(days)
# 3. 年月日を同時に抽出
print("n=== 年月日を同時に抽出 ===")
datetime_series = pd.to_datetime(dates)
df = pd.DataFrame({
'元の日付': datetime_series,
'年': datetime_series.dt.year,
'月': datetime_series.dt.month,
'日': datetime_series.dt.day
})
print(df)
# 4. 各月の日数を確認
print("n=== 各月の日数 ===")
dates_full = pd.date_range('2023-01-01', periods=12, freq='MS')
days_in_month = dates_full.dt.days_in_month
print(pd.DataFrame({
'月': dates_full,
'日数': days_in_month
}))
# 5. うるう年の2月の日数
print("n=== うるう年の2月の日数 ===")
leap_feb = pd.Timestamp('2024-02-01').days_in_month
print(f"2024年2月の日数: {leap_feb}")
non_leap_feb = pd.Timestamp('2023-02-01').days_in_month
print(f"2023年2月の日数: {non_leap_feb}")
# 1. 日時の Series を作成
print("=== 日時 Series の作成 ===")
dates = pd.Series([
'2023-01-15',
'2023-02-20',
'2023-03-05',
'2023-04-30',
'2023-05-25',
'2023-12-31'
])
# datetime 型に変換
datetime_series = pd.to_datetime(dates)
print("元の日付:")
print(datetime_series)
# 2. dt.day を使用して日を抽出
print("n=== dt.day を使用して日を抽出 ===")
days = datetime_series.dt.day
print("日:")
print(days)
# 3. 年月日を同時に抽出
print("n=== 年月日を同時に抽出 ===")
datetime_series = pd.to_datetime(dates)
df = pd.DataFrame({
'元の日付': datetime_series,
'年': datetime_series.dt.year,
'月': datetime_series.dt.month,
'日': datetime_series.dt.day
})
print(df)
# 4. 各月の日数を確認
print("n=== 各月の日数 ===")
dates_full = pd.date_range('2023-01-01', periods=12, freq='MS')
days_in_month = dates_full.dt.days_in_month
print(pd.DataFrame({
'月': dates_full,
'日数': days_in_month
}))
# 5. うるう年の2月の日数
print("n=== うるう年の2月の日数 ===")
leap_feb = pd.Timestamp('2024-02-01').days_in_month
print(f"2024年2月の日数: {leap_feb}")
non_leap_feb = pd.Timestamp('2023-02-01').days_in_month
print(f"2023年2月の日数: {non_leap_feb}")
実行結果:
=== 创建日期时间 Series ===
0 2023-01-15
1 2023-02-20
2 2023-03-05
3 2023-04-30
4 2023-05-25
5 2023-12-31
dtype: datetime64[ns]
=== 使用 dt.day 提取天 ===
天:
0 15
1 20
2 5
3 30
4 25
5 31
dtype: int64
=== 同时提取年月日 ===
原始日期 年 月 日
0 2023-01-15 2023 1 15
1 2023-02-20 2023 2 20
2 2023-03-05 2023 3 5
3 2023-04-30 2023 4 30
4 2023-05-25 2023 5 25
5 2023-12-31 2023 12 31
=== 各月的天数 ===
月份 天数
0 2023-01-01 31
1 2023-02-01 28
2 2023-03-01 31
3 2023-04-01 30
4 2023-05-01 31
5 2023-06-01 30
6 2023-07-01 31
7 2023-08-01 31
8 2023-09-01 30
9 2023-10-01 31
10 2023-11-01 30
11 2023-12-01 31
=== 闰年2月天数 ===
2024年2月天数: 29
2023年2月天数: 28
コードの解説:
dt.day1〜31 の整数を返し、月の第何日目かを表します。- 年月日を同時に抽出して、新しい DataFrame を作成できます。
days_in_monthこの属性を使用すると毎月の日数を取得でき、月末の日付の処理に役立ちます。- 2024年はうるう年で、2月は29日あります。2023年は平年で、2月は28日あります。
例2:日ごとのフィルタリングと分析
実例
import pandas as pd
import numpy as np
# 日付を含むデータセットを作成
print("=== 取引データの作成 ===")
np.random.seed(100)
# 30日分のデータを生成
dates = pd.date_range('2023-03-01', periods=30, freq='D')
df = pd.DataFrame({
'date': dates,
'transactions': np.random.randint(50, 200, 30),
'revenue': np.random.randint(5000, 20000, 30)
})
# 日を抽出
df['day'] = df['date'].dt.day
print(df.head(15))
# 特定の日のレコードをフィルタリング(例:毎月15日)
print("n=== 毎月15日の取引 ===")
day_15 = df[df['day'] == 15]
print(day_15)
# 月の前半と後半にフィルタリング
print("n=== 前半 vs 後半 ===")
df['half'] = df['day'].apply(lambda x: '前半' if x <= 15 else '後半')
half_stats = df.groupby('half')['transactions'].agg(['sum', 'mean']).round(2)
half_stats.columns = ['総取引数', '平均取引数']
print(half_stats)
# 日ごとに集計
print("n=== 日ごとの平均収入の集計 ===")
daily_avg = df.groupby('day')['revenue'].mean().round(2)
print(daily_avg)
# 収入が最も高い日を見つける
print("n=== 収入が最も高い日と最も低い日 ===")
max_day = df.loc[df['revenue'].idxmax()]
min_day = df.loc[df['revenue'].idxmin()]
print(f"最高収入: {max_day['date'].date()}、金額 {max_day['revenue']}")
print(f"最低収入: {min_day['date'].date()}、金額 {min_day['revenue']}")
import numpy as np
# 日付を含むデータセットを作成
print("=== 取引データの作成 ===")
np.random.seed(100)
# 30日分のデータを生成
dates = pd.date_range('2023-03-01', periods=30, freq='D')
df = pd.DataFrame({
'date': dates,
'transactions': np.random.randint(50, 200, 30),
'revenue': np.random.randint(5000, 20000, 30)
})
# 日を抽出
df['day'] = df['date'].dt.day
print(df.head(15))
# 特定の日のレコードをフィルタリング(例:毎月15日)
print("n=== 毎月15日の取引 ===")
day_15 = df[df['day'] == 15]
print(day_15)
# 月の前半と後半にフィルタリング
print("n=== 前半 vs 後半 ===")
df['half'] = df['day'].apply(lambda x: '前半' if x <= 15 else '後半')
half_stats = df.groupby('half')['transactions'].agg(['sum', 'mean']).round(2)
half_stats.columns = ['総取引数', '平均取引数']
print(half_stats)
# 日ごとに集計
print("n=== 日ごとの平均収入の集計 ===")
daily_avg = df.groupby('day')['revenue'].mean().round(2)
print(daily_avg)
# 収入が最も高い日を見つける
print("n=== 収入が最も高い日と最も低い日 ===")
max_day = df.loc[df['revenue'].idxmax()]
min_day = df.loc[df['revenue'].idxmin()]
print(f"最高収入: {max_day['date'].date()}、金額 {max_day['revenue']}")
print(f"最低収入: {min_day['date'].date()}、金額 {min_day['revenue']}")
実行結果:
=== 创建交易数据 ===
date transactions revenue day
0 2023-03-01 73 16200 1
1 2023-03-02 163 18800 2
2 2023-03-03 76 9600 3
3 2023-03-04 83 10500 4
4 2023-03-05 136 16200 5
5 2023-03-06 86 11700 6
6 2023-03-07 87 13400 7
7 2023-03-08 168 14200 8
8 2023-03-09 163 15800 9
9 2023-03-10 82 11000 10
10 2023-03-11 106 14600 11
11 2023-03-12 152 15900 12
12 2023-03-13 数据截断...
=== 每月15号的交易 ===
date transactions revenue day
14 2023-03-15 104 12900 15
=== 上半月 vs 下半月 ===
总交易数 平均交易数
下半月 2117 111.42
上半月 1873 117.06
=== 按天统计平均收入 ===
day
1 16200.00
2 18800.00
...
=== 收入最高和最低的天 ===
最高收入: 2023-03-02,金额 18800
最低收入: 2023-03-03,金额 9600
コードの解説:
- 日ごとにフィルタリングやグループ分析ができます。
- 日を月の前半と後半に分けて分析できます。
idxmax()とidxmin()最大値・最小値に対応するレコードをすばやく見つけられます。
例3:月末の日付処理
実例
import pandas as pd
# 1. 異なる月の最後の日を処理
print("=== 各月の最後の日 ===")
dates = pd.date_range('2023-01-01', periods=12, freq='MS')
print("毎月の最初の日:")
print(dates)
# 毎月の最後の日を取得
last_days = dates + pd.offsets.MonthEnd(0)
print("n毎月の最後の日:")
print(last_days)
# 2. 月末かどうかを判定
print("n=== 月末かどうかの判定 ===")
test_dates = pd.Series([
'2023-01-30', # 1月30日(月末ではない)
'2023-01-31', # 1月31日(月末)
'2023-02-28', # 2月28日(平年)
'2023-04-30', # 4月30日(月末)
])
dt_series = pd.to_datetime(test_dates)
is_month_end = dt_series.is_month_end
result = pd.DataFrame({
'日付': dt_series,
'月末かどうか': is_month_end
})
print(result)
# 3. 月初の日付処理
print("n=== 月初かどうかの判定 ===")
is_month_start = dt_series.is_month_start
result['月初かどうか'] = is_month_start
print(result)
# 4. 月の日数が異なる場合の処理
print("n=== 月の日数が異なる場合の処理 ===")
dates_to_check = pd.Series([
'2023-01-31', # 有効な日付
'2023-02-30', # 無効な日付(2月に30日はない)
])
# 変換を試みて無効な日付を処理
try:
valid_dates = pd.to_datetime(dates_to_check, errors='coerce')
print("変換後の日付:")
print(valid_dates)
print("n各日付に対応する日:")
print(valid_dates.dt.day)
except Exception as e:
print(f"エラー: {e}")
# 1. 異なる月の最後の日を処理
print("=== 各月の最後の日 ===")
dates = pd.date_range('2023-01-01', periods=12, freq='MS')
print("毎月の最初の日:")
print(dates)
# 毎月の最後の日を取得
last_days = dates + pd.offsets.MonthEnd(0)
print("n毎月の最後の日:")
print(last_days)
# 2. 月末かどうかを判定
print("n=== 月末かどうかの判定 ===")
test_dates = pd.Series([
'2023-01-30', # 1月30日(月末ではない)
'2023-01-31', # 1月31日(月末)
'2023-02-28', # 2月28日(平年)
'2023-04-30', # 4月30日(月末)
])
dt_series = pd.to_datetime(test_dates)
is_month_end = dt_series.is_month_end
result = pd.DataFrame({
'日付': dt_series,
'月末かどうか': is_month_end
})
print(result)
# 3. 月初の日付処理
print("n=== 月初かどうかの判定 ===")
is_month_start = dt_series.is_month_start
result['月初かどうか'] = is_month_start
print(result)
# 4. 月の日数が異なる場合の処理
print("n=== 月の日数が異なる場合の処理 ===")
dates_to_check = pd.Series([
'2023-01-31', # 有効な日付
'2023-02-30', # 無効な日付(2月に30日はない)
])
# 変換を試みて無効な日付を処理
try:
valid_dates = pd.to_datetime(dates_to_check, errors='coerce')
print("変換後の日付:")
print(valid_dates)
print("n各日付に対応する日:")
print(valid_dates.dt.day)
except Exception as e:
print(f"エラー: {e}")
実行結果:
=== 各月最后一天 ===
每月第一天:
DatetimeIndex(['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01',
'2023-05-01', '2023-06-01', '2023-07-01', '2023-03-01',
'2023-09-01', '2023-10-01', '2023-11-01', '2023-12-01'],
dtype='datetime64[ns]', freq=None)
每月最后一天:
DatetimeIndex(['2023-01-31', '2023-02-28', '2023-03-31', '2023-04-30',
'2023-05-31', '2023-06-30', '2023-07-31', '2023-03-31',
'2023-09-30', '2023-10-31', '2023-11-30', '2023-12-31'],
dtype='datetime64[ns]', freq=None)
=== 判断是否为月末 ===
日期 是否为月末
0 2023-01-30 False
1 2023-01-31 True
2 2023-02-28 True
3 2023-04-30 True
=== 判断是否为月初 ===
日期 是否为月末 是否为月初
0 2023-01-30 False False
1 2023-01-31 False False
2 2023-02-28 False False
3 2023-04-30 False False
=== 月份天数不一致的处理 ===
转换后的日期:
0 2023-01-31
1 NaT
Name: date, dtype: datetime64[ns]
各日期对应的天:
0 31.0
1 NaN
コードの解説:
is_month_endこの属性を使用すると月末かどうかを判定できます。is_month_startこの属性を使用すると月初かどうかを判定できます。pd.offsets.MonthEnd(0)当月の最後の日を取得できます。- 無効な日付を処理する場合は、
errors='coerce'を使用して無効な日付を NaT に変換できます。
注意事項
重要な注意:
Series.dt.daydatetime64 型の Series にのみ使用できます。- 返される日の範囲は 1〜31 で、具体的な最大値は月によって異なります(2月は最大28/29日、4/6/9/11月は30日、その他の月は31日)。
- を使用することで、
dt.days_in_month毎月の日数を取得できます。- 欠損値(NaT)を含むデータを処理する場合、
dt.day対応する位置に NaT が返されます。
その他の拡張
Pandas 常用関数