Свойство Pandas Series.dt.day

Pandas 通用函数Pandas: общие функции


Series.dt.day— это атрибут Pandas, используемый дляизвлечения дня (даты) из даты-времени. Он является частью аксессора dt и позволяет быстро извлечь день месяца (1-31) из Series с datetime.

При анализе данных временных рядов анализ по дням является обычным требованием, например анализ конкретных дней каждого месяца, выявление периодических закономерностей и т. д.dt.dayЭто свойство делает такие операции простыми и эффективными.

Определение слова: dayОно означает «day», то есть возвращает день в дате (день месяца).


Базовый синтаксис и параметры

Series.dt.dayЭто атрибут аксессора dt объекта Series, используемый для извлечения дня.

Формат синтаксиса

Series.dt.day

Описание параметра

Этот атрибут не требует параметров; он напрямую обращается к информации о дне в Series с datetime.

Описание возвращаемого значения

  • Возвращаемое значениеВозвращает целочисленный Series, содержащий день (1-31).
  • ДействиеИзвлекает часть даты, соответствующую дню, из Series с datetime64, возвращая целые числа от 1 до 31.

Пример

Давайте досконально освоим с помощью серии примеров от простых к сложнымSeries.dt.dayиспользование этого свойства.

Пример 1: Базовое использование - Извлечение дня

Пример

import pandas as pd

# 1. Создайте Series с datetime
print("=== Создание Series типа datetime ===")
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. Количество дней в феврале в високосном году
print("\n=== Количество дней в феврале в високосном году ===")
leap_feb = pd.Timestamp('2024-02-01').days_in_month
print(f"Количество дней в феврале 2024: {leap_feb}")
non_leap_feb = pd.Timestamp('2023-02-01').days_in_month
print(f"Количество дней в феврале 2023: {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 — високосный год, в феврале 29 дней; 2023 — обычный год, в феврале 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': даты,
    '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=== Первая половина против второй половины ===")
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 = ['Total transactions', 'Average transactions']
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',  # 30 января (не последний день месяца)
    '2023-01-31',  # 31 января (последний день месяца)
    '2023-02-28',  # 28 февраля (невисокосный год)
    '2023-04-30',  # 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',  # Некорректная дата (в феврале нет 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Его можно использовать только для Series типа datetime64.
  • Возвращаемый диапазон дней — 1–31; точный максимум зависит от месяца (в феврале максимум 28/29 дней, в апреле/июне/сентябре/ноябре — 30 дней, а в остальных месяцах — 31 день).
  • Вы можете использоватьdt.days_in_monthчтобы получить количество дней в каждом месяце.
  • При обработке данных, содержащих пропущенные значения (NaT),dt.dayNaT будет возвращено в соответствующей позиции.

Pandas 常用函数Pandas: общие функции

Другие расширения