Эффективное преобразование временных меток с учетом часового пояса в datetime64[m] в Pandas

У меня есть следующий код, который создает DataFrame, представляющий данные, которые есть в моей системе:

import pandas as pd

data = {
    "date": [
        "2021-03-12 19:50:00-05:00", "2021-03-12 19:51:00-05:00", "2021-03-12 19:52:00-05:00",
        "2021-03-12 19:53:00-05:00", "2021-03-12 19:54:00-05:00", "2021-03-12 19:55:00-05:00",
        "2021-03-12 19:56:00-05:00", "2021-03-12 19:57:00-05:00", "2021-03-12 19:58:00-05:00",
        "2021-03-12 19:59:00-05:00", "2021-03-15 04:00:00-04:00", "2021-03-15 04:01:00-04:00",
        "2021-03-15 04:02:00-04:00", "2021-03-15 04:03:00-04:00", "2021-03-15 04:04:00-04:00",
        "2021-03-15 04:05:00-04:00", "2021-03-15 04:06:00-04:00", "2021-03-15 04:07:00-04:00",
        "2021-03-15 04:08:00-04:00", "2021-03-15 04:09:00-04:00"
    ],
    "open": [81.15, 81.14, 81.15, 81.15, 81.15, 81.17, 81.19, 81.19, 81.20, 81.23, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05],
    "high": [81.15, 81.14, 81.15, 81.15, 81.17, 81.17, 81.19, 81.19, 81.20, 81.23, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05],
    "low": [81.14, 81.14, 81.14, 81.15, 81.15, 81.17, 81.19, 81.19, 81.20, 81.23, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05],
    "close": [81.14, 81.14, 81.15, 81.15, 81.17, 81.17, 81.19, 81.19, 81.20, 81.23, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05, 81.05],
    "volume": [300.0, 100.0, 1684.0, 0.0, 1680.0, 150.0, 448.0, 0.0, 1500.0, 380.0, 162.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
}

df = pd.DataFrame(data)

print(df.info())

Результат:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   date    20 non-null     object 
 1   open    20 non-null     float64
 2   high    20 non-null     float64
 3   low     20 non-null     float64
 4   close   20 non-null     float64
 5   volume  20 non-null     float64
dtypes: float64(5), object(1)
memory usage: 1.1+ KB

Тип данных столбца date: object — это временная метка с учетом часового пояса.

Временные метки содержат информацию о часовом поясе, которую мне нужно удалить, а затем преобразовать столбец date в datetime64[m] (с точностью до минуты), но после применения следующего кода преобразования:

df['date'] = df['date'].apply(lambda ts: pd.Timestamp(ts).tz_localize(None).to_numpy().astype('datetime64[m]'))

print(df.info())

Вывод показывает, что столбец date имеет тип данных datetime64[ns] вместо datetime64[m]:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   date    20 non-null     datetime64[ns]
 1   open    20 non-null     float64       
 2   high    20 non-null     float64       
 3   low     20 non-null     float64       
 4   close   20 non-null     float64       
 5   volume  20 non-null     float64       
dtypes: datetime64 , float64(5)
memory usage: 1.1 KB

Как я могу правильно преобразовать столбец date с данными о часовом поясе в datetime64[m] наиболее эффективным способом с точки зрения использования памяти?

🤔 А знаете ли вы, что...
Python имеет богатую стандартную библиотеку, включая модули для работы с текстом, файлами и сетями.


2
65
1

Ответ:

Решено

К сожалению, для pandas datetime не существует «минутной» единицы. Ты можно выбрать "D,s,ms,us,n" день, секунду, миллисекунду, микросекунду или наносекунду соответственно. Этот список можно найти под аргументом "unit" в документации pandas.to_datetime

Тем не менее, вы все равно можете проанализировать эти данные и преобразовать их в секунды. Ключевым моментом здесь является понимание того, что панды не могут справиться с отдельной информацией о часовом поясе (-05:00 и -04:00). в одной серии (столбце). Он может поддерживать часовой пояс + различную информацию о переходе на летнее время (как я подозреваю, здесь дело в этом), но поскольку неясно, так ли это, нам нужно будет пройдите через UTC, а затем позвольте преобразованию в наш часовой пояс обрабатывать, будет ли что-то в летнем режиме или нет.

import pandas as pd

data = {
    'raw': [
        '2021-03-12 19:50:00-05:00', '2021-03-12 19:51:00-05:00', '2021-03-12 19:52:00-05:00',
        '2021-03-12 19:53:00-05:00', '2021-03-12 19:54:00-05:00', '2021-03-12 19:55:00-05:00',
        '2021-03-12 19:56:00-05:00', '2021-03-12 19:57:00-05:00', '2021-03-12 19:58:00-05:00',
        '2021-03-12 19:59:00-05:00', '2021-03-15 04:00:00-04:00', '2021-03-15 04:01:00-04:00',
        '2021-03-15 04:02:00-04:00', '2021-03-15 04:03:00-04:00', '2021-03-15 04:04:00-04:00',
        '2021-03-15 04:05:00-04:00', '2021-03-15 04:06:00-04:00', '2021-03-15 04:07:00-04:00',
        '2021-03-15 04:08:00-04:00', '2021-03-15 04:09:00-04:00'
    ],
}
df = pd.DataFrame(data)

df['parsed_w_timezone'] = (
    pd.to_datetime(df['raw'], format='%Y-%m-%d %H:%M:%S%z', utc=True) # 1. parse into utc
    .dt.tz_convert('US/Eastern')                                      # 2. convert to US/Eastern
    .astype('datetime64[s, US/Eastern]')                              # 3. convert nanoseconds → seconds unit
)
df['parsed_wo_timezone'] = df['parsed_w_timezone'].dt.tz_localize(None)

print(df.dtypes)
# raw                                      object
# parsed_w_timezone     datetime64[s, US/Eastern]
# parsed_wo_timezone                datetime64[s]
# dtype: object

print(df.to_string(col_space=30, index=False, justify='left'))
# raw                            parsed_w_timezone              parsed_wo_timezone
# 2021-03-12 19:50:00-05:00      2021-03-12 19:50:00-05:00      2021-03-12 19:50:00
# 2021-03-12 19:51:00-05:00      2021-03-12 19:51:00-05:00      2021-03-12 19:51:00
# 2021-03-12 19:52:00-05:00      2021-03-12 19:52:00-05:00      2021-03-12 19:52:00
# 2021-03-12 19:53:00-05:00      2021-03-12 19:53:00-05:00      2021-03-12 19:53:00
# 2021-03-12 19:54:00-05:00      2021-03-12 19:54:00-05:00      2021-03-12 19:54:00
# 2021-03-12 19:55:00-05:00      2021-03-12 19:55:00-05:00      2021-03-12 19:55:00
# 2021-03-12 19:56:00-05:00      2021-03-12 19:56:00-05:00      2021-03-12 19:56:00
# 2021-03-12 19:57:00-05:00      2021-03-12 19:57:00-05:00      2021-03-12 19:57:00
# 2021-03-12 19:58:00-05:00      2021-03-12 19:58:00-05:00      2021-03-12 19:58:00
# 2021-03-12 19:59:00-05:00      2021-03-12 19:59:00-05:00      2021-03-12 19:59:00
# 2021-03-15 04:00:00-04:00      2021-03-15 04:00:00-04:00      2021-03-15 04:00:00
# 2021-03-15 04:01:00-04:00      2021-03-15 04:01:00-04:00      2021-03-15 04:01:00
# 2021-03-15 04:02:00-04:00      2021-03-15 04:02:00-04:00      2021-03-15 04:02:00
# 2021-03-15 04:03:00-04:00      2021-03-15 04:03:00-04:00      2021-03-15 04:03:00
# 2021-03-15 04:04:00-04:00      2021-03-15 04:04:00-04:00      2021-03-15 04:04:00
# 2021-03-15 04:05:00-04:00      2021-03-15 04:05:00-04:00      2021-03-15 04:05:00
# 2021-03-15 04:06:00-04:00      2021-03-15 04:06:00-04:00      2021-03-15 04:06:00
# 2021-03-15 04:07:00-04:00      2021-03-15 04:07:00-04:00      2021-03-15 04:07:00
# 2021-03-15 04:08:00-04:00      2021-03-15 04:08:00-04:00      2021-03-15 04:08:00
# 2021-03-15 04:09:00-04:00      2021-03-15 04:09:00-04:00      2021-03-15 04:09:00