Передача datetime64[ns] из фрейма данных pandas в качестве аргумента функции

#python #pandas #function #dataframe #datetime

#python #pandas #функция #фрейм данных #datetime

Вопрос:

Я пытаюсь создать дополнительный столбец во фрейме данных, чтобы показать количество сетевых дней (за исключением пользовательских праздников) между двумя датами. Я использую функцию, которой я пытаюсь передать даты из df столбцов в качестве аргументов, но я не могу заставить ее работать.

Ниже приведен мой код (я использую два выдуманных праздника в данном наборе):

 from networkdays import networkdays
import datetime as dt
import numpy as np
import pandas as pd

public_holidays_list = [dt.date(2021, 1, 6), dt.date(2021, 1, 7)]
public_holidays = set(public_holidays_list)

def working_days(start, end, holidays):
    days = networkdays.Networkdays(start, end, holidays)
    working_days = len(days.networkdays())
    return working_days
 

Сама формула работает нормально:

 print(working_days(dt.date(2021, 1, 4), dt.date(2021, 1, 8), public_holidays))
 

3

Минимальный фрейм данных с тем dtypes , над которым я работаю:

 d = {'Name': ['A', 'B'], 'Start_Date': [dt.date(2021, 1, 4), dt.date(2021, 1, 11)], 'End_Date': [dt.date(2021, 1, 8), dt.date(2021, 1, 15)]}
df = pd.DataFrame(data = d)
df['Start_Date'] = pd.to_datetime(df['Start_Date'])
df['End_Date'] = pd.to_datetime(df['End_Date'])
 

Когда я пытаюсь использовать приведенный ниже способ…

 df['Working_Days'] = working_days(df['Start_Date'], df['End_Date'])
 

…Я получаю сообщение об ошибке:

Ошибка атрибута: объект ‘Series’ не имеет атрибута ‘days’

Я также пытался использовать numpy :

 df['Working_Days'] = np.vectorize(working_days)(df['Start_Date'], df['End_Date'])
 

Я также получил ошибку:

Ошибка атрибута: объект ‘numpy.timedelta64’ не имеет атрибута ‘days’

Не могли бы вы указать мне правильное направление?

РЕДАКТИРОВАТЬ: правильный ответ на мою проблему — последний комментарий @Kris.

ВАЖНО!Хотя lambda он не возвращает никаких ошибок, он public_holidays правильно учитывает 2 сценария:

A) Элементы public_holidays относятся к классу datetime.date , а df даты относятся к классу object (я получил это, удалив pd.to_datetime() строки из кода).

Б) public_holidays Имеет тип list (создается из таблицы Excel с помощью public_holidays = df_ph['Date'].tolist() ), его элементы имеют класс Timestamp , а pd.to_datetime() строки не удаляются из приведенного выше кода (ввод дат df datetime64[ns] ).

Комментарии:

1. Найдите apply . Например, df['Working_Days'] = df.apply(lambda x: working_days(x.Start_Date, x.End_Date), axis=1) может сработать.

2. @Kris , теперь он вычисляет дни, но без учета государственных праздников. Я обновил функцию третьим аргументом — можете ли вы сказать мне, как я могу передать его lambda , поскольку он находится «снаружи» фрейма данных?

3. Добавьте .dt к каждому из ваших аргументов

4. @Witherfield вы должны иметь возможность просто передать его как обычно, например df.apply(lambda x: working_days(x.Start_Date, x.End_Date, public_holidays), axis=1) . Я бы написал полный ответ, но я не могу использовать networkdays .

5. @Kris, это действительно работает, спасибо! Не могли бы вы опубликовать свой комментарий в качестве ответа, чтобы я мог его принять?

Ответ №1:

Согласно моему комментарию, используйте .apply :

 df['Working_Days'] = df.apply(lambda x: working_days(x.Start_Date, x.End_Date, public_holidays), axis=1)