Pandas Series.dt.day 属性
Series.dt.day 是 Pandas 中用于提取日期时间中的天(日期)的属性。它是 dt 访问器的一部分,可以从 datetime 类型的 Series 中快速提取一个月中的第几天(1-31)。
在时间序列数据分析中,按天进行分析是常见需求,例如分析每月的某几天、识别周期性模式等。dt.day 属性使得这类操作变得简单高效。
单词释义: day 意为"日",即返回日期中的天(月份中的第几天)。
基本语法与参数
Series.dt.day 是 Series 的 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.day返回 1-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.day只能用于 datetime64 类型的 Series。- 返回的天数范围是 1-31,具体最大值取决于月份(2月最大28/29天,4/6/9/11月30天,其他月份31天)。
- 可以使用
dt.days_in_month获取每月的天数。- 处理包含缺失值(NaT)的数据时,
dt.day会返回对应位置的 NaT。

Pandas 常用函数