Как применить функцию к списку отметок времени для создания pandas ser ie? - PullRequest
0 голосов
/ 19 февраля 2020

ОК, рабочая часть кода: у меня есть функция, которая задает метку времени, а точка (минута, час, месяц ...) возвращает длительность периода в виде временной шкалы. В основном, для минуты, часа, дня он напрямую вызывает функцию pandas Timedelta. Для месяца это немного «умнее», так как он проверяет, в каком месяце находится отметка времени, и возвращает количество дней идентифицированного месяца.

import pandas as pd

def as_timedelta(ref_ts: pd.Timestamp = None):
    """
    Return the duration of a time period.
    For a month, obtaining its duration requires a reference timestamp to identify
    how many days have to be accounted for in the month.
    """

    # An input timestamp has to be given.
    # It is assumed given timestamp is at beginning of time period for which a time delta is requested.
    # Because of a possible timezone, the timestamp is max 12 hours before or after
    # beginning of month in UTC.
    # To assume the current month, we check what is the closest month beginning
    # As an example, if 31st of January, 6:00 PM is reference timestamp, duration is given for month of February

    # Get month starts
    current_month = pd.Timestamp(year=ref_ts.year, month=ref_ts.month, day=1)
    next_month = current_month + pd.DateOffset(months=1)
    nex_next_month = current_month + pd.DateOffset(months=2)
    # Get month of interest
    dist_to_next = next_month - ref_ts
    dist_to_prev = ref_ts - current_month
    # Return timedelta corresponding as the duration between current month and begining of next month
    td_13 = pd.Timedelta(13, 'h')
    if dist_to_next < td_13:
        return nex_next_month - next_month
    elif dist_to_prev < td_13:
        return next_month - current_month

Учитывая список отметок времени, я хотел бы применить эта функция для каждой метки времени. Но пытаясь с помощью следующей строки кода, но я получаю AttributeError. Чтобы проиллюстрировать проблему сейчас, я беру пример:

ts_list_1M = [
          "Thu Feb 01 2019 00:00:00 GMT+0100",
          "Thu Mar 01 2019 00:00:00 GMT+0100",
          "Sun Apr 01 2019 00:00:00 GMT+0200"]
op_list_1M = [7134.0, 7134.34, 7135.03]
GC_1M = pd.DataFrame(list(zip(ts_list_1M, op_list_1M)), columns =['date', 'open'])
GC_1M['date'] = pd.to_datetime(GC_1M['date'], utc=True)
GC_1M.rename(columns={'date': 'Timestamp'}, inplace=True)
GC_1M.set_index('Timestamp', inplace = True, verify_integrity = True)

Знаменитая строка кода:

GC_1M.reset_index().apply(as_timedelta,axis=1).values

И сообщение об ошибке, которое я получаю:

File "<ipython-input-49-ff9556f2ec44>", line 18, in as_timedelta
current_month = pd.Timestamp(year=ref_ts.year, month=ref_ts.month, day=1)

File "C:\Users\pierre.juillard\Documents\Programs\Anaconda\lib\site-packages\pandas\core\generic.py", line 5179, in __getattr__
return object.__getattribute__(self, name)

AttributeError: ("'Series' object has no attribute 'year'", 'occurred at index 0')

Когда я проверяю функцию на одном значении, она работает, но при ее применении таким образом - нет. Пожалуйста, какой-нибудь совет, как этого добиться?

Заранее благодарю за помощь! Bests,

1 Ответ

1 голос
/ 19 февраля 2020

Поэтому, когда вы хотите применить свою функцию только к вашей серии «дат», вы можете сделать следующее:

GC_1M['date'].apply(as_timedelta)

Однако, похоже, это не сработает, как в вашем примере 'date' это не объект даты и времени, поэтому вам необходимо сначала преобразовать его (вы также можете сделать это при создании):

GC_1M['date'] = pd.to_datetime(GC_1M['date'])

И, наконец, ваша функция as_timedelta не может работать с входными данными с учетом часового пояса, добавил я комментарий к строке, требующей исправления:

def as_timedelta(ref_ts: pd.Timestamp = None):
    """
    Return the duration of a time period.
    For a month, obtaining its duration requires a reference timestamp to identify
    how many days have to be accounted for in the month.
    """

    # An input timestamp has to be given.
    # It is assumed given timestamp is at beginning of time period for which a time delta is requested.
    # Because of a possible timezone, the timestamp is max 12 hours before or after
    # beginning of month in UTC.
    # To assume the current month, we check what is the closest month beginning
    # As an example, if 31st of January, 6:00 PM is reference timestamp, duration is given for month of February

    # Get month starts
    current_month = pd.Timestamp(year=ref_ts.year, month=ref_ts.month, day=1, tzinfo=ref_ts.tzinfo)  # Make current_month timezone aware
    next_month = current_month + pd.DateOffset(months=1)
    nex_next_month = current_month + pd.DateOffset(months=2)
    # Get month of interest
    dist_to_next = next_month - ref_ts
    dist_to_prev = ref_ts - current_month
    # Return timedelta corresponding as the duration between current month and begining of next month
    td_13 = pd.Timedelta(13, 'h')
    if dist_to_next < td_13:
        return nex_next_month - next_month
    elif dist_to_prev < td_13:
        return next_month - current_month
...