现在位置: 首页 > Pandas 教程 > 正文

Pandas Series.dt.day 属性

Pandas 通用函数 Pandas 常用函数


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}")

运行结果:

=== 创建日期时间 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

代码解析:

  1. dt.day 返回 1-31 的整数,表示一个月中的第几天。
  2. 可以同时提取年月日创建新的 DataFrame。
  3. days_in_month 属性可以获取每月的天数,对处理月末日期很有用。
  4. 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']}")

运行结果:

=== 创建交易数据 ===
         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}")

运行结果:

=== 各月最后一天 ===
每月第一天:
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 常用函数 Pandas 常用函数