Polars的replace_time_zone和convert_time_zone对于相同的时区转换显示不同的字符串表示形式

2023-12-28

测试数据:

import polars as pl
import pandas as pd
from datetime import date, time, datetime

# polars df for Jan to 12th, March 2022 before DST transition.
tdf = pl.DataFrame(
    pl.date_range(
        low=date(2022, 1, 3),
        high=date(2022, 3, 12),
        interval="5m",
        time_unit="ns",
        time_zone="UTC",
    ).alias("UTC")
)

我的用例是将 UTC 数据(或不了解时区)转换为 EST/EDT 数据(或了解时区),然后在时间范围(9:30 到 16:00)上过滤数据。

tz_replaced_filtered = tdf.with_columns( 
    pl.col("UTC").dt.replace_time_zone(time_zone="US/Eastern").alias("NY")
).filter(
  pl.col("NY").cast(pl.Time).is_between(time(9), time(16), closed="both")
)

# output
shape: (5780, 2)
┌─────────────────────────┬──────────────────────────┐
│ UTC                     ┆ NY                       │
│ ---                     ┆ ---                      │
│ datetime[ns, UTC]       ┆ datetime[ns, US/Eastern] │
╞═════════════════════════╪══════════════════════════╡
│ 2022-01-03 04:00:00 UTC ┆ 2022-01-03 04:00:00 EST  │
│ 2022-01-03 04:05:00 UTC ┆ 2022-01-03 04:05:00 EST  │
│ 2022-01-03 04:10:00 UTC ┆ 2022-01-03 04:10:00 EST  │
│ 2022-01-03 04:15:00 UTC ┆ 2022-01-03 04:15:00 EST  │
│ …                       ┆ …                        │
│ 2022-03-11 10:45:00 UTC ┆ 2022-03-11 10:45:00 EST  │
│ 2022-03-11 10:50:00 UTC ┆ 2022-03-11 10:50:00 EST  │
│ 2022-03-11 10:55:00 UTC ┆ 2022-03-11 10:55:00 EST  │
│ 2022-03-11 11:00:00 UTC ┆ 2022-03-11 11:00:00 EST  │
└─────────────────────────┴──────────────────────────┘

显然这个结果中没有明显的 9 到 16 时间范围df.

我进一步探究:

tz_replaced_filtered.with_columns(
   pl.col("NY").cast(pl.Time).alias("NY_TIME"),
   pl.col("UTC").cast(pl.Time).alias("UTC_TIME")
)

# output
shape: (5780, 4)
┌─────────────────────────┬──────────────────────────┬──────────┬──────────┐
│ UTC                     ┆ NY                       ┆ NY_TIME  ┆ UTC_TIME │
│ ---                     ┆ ---                      ┆ ---      ┆ ---      │
│ datetime[ns, UTC]       ┆ datetime[ns, US/Eastern] ┆ time     ┆ time     │
╞═════════════════════════╪══════════════════════════╪══════════╪══════════╡
│ 2022-01-03 04:00:00 UTC ┆ 2022-01-03 04:00:00 EST  ┆ 09:00:00 ┆ 04:00:00 │
│ 2022-01-03 04:05:00 UTC ┆ 2022-01-03 04:05:00 EST  ┆ 09:05:00 ┆ 04:05:00 │
│ 2022-01-03 04:10:00 UTC ┆ 2022-01-03 04:10:00 EST  ┆ 09:10:00 ┆ 04:10:00 │
│ 2022-01-03 04:15:00 UTC ┆ 2022-01-03 04:15:00 EST  ┆ 09:15:00 ┆ 04:15:00 │
│ …                       ┆ …                        ┆ …        ┆ …        │
│ 2022-03-11 10:45:00 UTC ┆ 2022-03-11 10:45:00 EST  ┆ 15:45:00 ┆ 10:45:00 │
│ 2022-03-11 10:50:00 UTC ┆ 2022-03-11 10:50:00 EST  ┆ 15:50:00 ┆ 10:50:00 │
│ 2022-03-11 10:55:00 UTC ┆ 2022-03-11 10:55:00 EST  ┆ 15:55:00 ┆ 10:55:00 │
│ 2022-03-11 11:00:00 UTC ┆ 2022-03-11 11:00:00 EST  ┆ 16:00:00 ┆ 11:00:00 │
└─────────────────────────┴──────────────────────────┴──────────┴──────────┘

底层时间戳似乎确实表明我成功地在时间范围 9 到 16 上进行了过滤;这只是不同步的字符串表示形式。

 tdf.with_columns(
     pl.col("UTC").dt.replace_time_zone(time_zone="US/Eastern").alias("NY_REPLACED"),
     pl.col("UTC").dt.convert_time_zone(time_zone="US/Eastern").alias("NY_CONVERTED")
 )

# output
shape: (19585, 3)
┌─────────────────────────┬──────────────────────────┬──────────────────────────┐
│ UTC                     ┆ NY_REPLACED              ┆ NY_CONVERTED             │
│ ---                     ┆ ---                      ┆ ---                      │
│ datetime[ns, UTC]       ┆ datetime[ns, US/Eastern] ┆ datetime[ns, US/Eastern] │
╞═════════════════════════╪══════════════════════════╪══════════════════════════╡
│ 2022-01-03 00:00:00 UTC ┆ 2022-01-03 00:00:00 EST  ┆ 2022-01-02 19:00:00 EST  │
│ 2022-01-03 00:05:00 UTC ┆ 2022-01-03 00:05:00 EST  ┆ 2022-01-02 19:05:00 EST  │
│ 2022-01-03 00:10:00 UTC ┆ 2022-01-03 00:10:00 EST  ┆ 2022-01-02 19:10:00 EST  │
│ 2022-01-03 00:15:00 UTC ┆ 2022-01-03 00:15:00 EST  ┆ 2022-01-02 19:15:00 EST  │
│ …                       ┆ …                        ┆ …                        │
│ 2022-03-11 23:45:00 UTC ┆ 2022-03-11 23:45:00 EST  ┆ 2022-03-11 18:45:00 EST  │
│ 2022-03-11 23:50:00 UTC ┆ 2022-03-11 23:50:00 EST  ┆ 2022-03-11 18:50:00 EST  │
│ 2022-03-11 23:55:00 UTC ┆ 2022-03-11 23:55:00 EST  ┆ 2022-03-11 18:55:00 EST  │
│ 2022-03-12 00:00:00 UTC ┆ 2022-03-12 00:00:00 EST  ┆ 2022-03-11 19:00:00 EST  │
└─────────────────────────┴──────────────────────────┴──────────────────────────┘

最后一步的结论是replaced_time_zone and convert_time_zone不会为相同的时区转换操作生成相同的字符串表示形式。

进一步来说,replaced_time_zone确实替换了底层时间戳,但它不会“替换”字符串表示形式;什么replaced_time_zone表面上对于 UTC(或者只是不知道时区的时间戳)来说就像with_time_zone,即简单地将时区信息附加到现有时间戳上。

如果有人能澄清上述问题,我将不胜感激。

问题背景

这是针对 Polars 用户和开发人员的,以便我提出的所有与时区转换相关的问题polars可以方便地参考。

我首先提出this https://stackoverflow.com/questions/74165901/polars-add-substract-utc-offset-from-datetime-object看看我们如何根据转换后的时间戳(考虑 utc 偏移量)进行过滤,然后polars假如replace_time_zone a question https://stackoverflow.com/questions/75793219/polars-replace-time-zone-function-throws-error-of-no-such-local-time因为它也被提高了。

@FObersteiner 提到的一个相关问题是here https://stackoverflow.com/questions/75268283/how-to-truncate-a-datetime-to-just-the-day.

暂时我的理解是replace_time_zone应该提供相同的字符串表示形式convert_time_zone,因为本质上他们所做的事情是相同的。这将使过滤日期/时间范围polarsWYSIWYG(所见即所得)。

背景资料

Polars提供replace_time_zone and convert_time_zone来处理这样的场景。

convert_time_zone仅更改呈现给用户的字符串表示形式,而不更改底层时间戳。所以cast在我的用例中,它不适用于“转换后的”时间戳(过滤仍然在原始的底层时间戳上)。

关于replace_time_zone, DST 转换导致problem https://stackoverflow.com/questions/75793219/polars-replace-time-zone-function-throws-error-of-no-such-local-time当用户尝试replace_time_zone鉴于由于 DST 转换而导致特定时间戳不存在,这个问题似乎是普遍存在的:

# demo polars df
tpl = pl.DataFrame(
   pl.date_range(
        low=date(2022, 3, 13),
        high=date(2022, 3, 15),
        interval="5m",
        time_unit="ns",
        time_zone="UTC",
   ).alias("UTC")
)

tpl.select(
   pl.col("UTC").dt.replace_time_zone(time_zone="America/New_York").alias("NY")
)

# Panic Exception: no such local time

# demo pandas pf
tpn = pd.DataFrame(
    pd.date_range(start="2022-03-13", 
                  end="2022-03-15",
                  freq="5T", # 5 minute interval
                  tz=None, # default to UTC
                  inclusive="both"),
    columns=["UTC"]
)

tpn.UTC.dt.tz_localize("America/New_York")

# NonExistentTimeError: 2022-03-13 02:00:00

我认为你遇到的问题是pl.cast(pl.Time)不转换为当地时间。

您可能想使用过滤.dt.hour():

In [23]: tz_replaced_filtered.filter(pl.col('NY').dt.hour().is_between(9, 16))
Out[23]:
shape: (6528, 2)
┌─────────────────────────┬──────────────────────────┐
│ UTC                     ┆ NY                       │
│ ---                     ┆ ---                      │
│ datetime[ns, UTC]       ┆ datetime[ns, US/Eastern] │
╞═════════════════════════╪══════════════════════════╡
│ 2022-01-03 09:00:00 UTC ┆ 2022-01-03 09:00:00 EST  │
│ 2022-01-03 09:05:00 UTC ┆ 2022-01-03 09:05:00 EST  │
│ 2022-01-03 09:10:00 UTC ┆ 2022-01-03 09:10:00 EST  │
│ 2022-01-03 09:15:00 UTC ┆ 2022-01-03 09:15:00 EST  │
│ …                       ┆ …                        │
│ 2022-03-11 16:40:00 UTC ┆ 2022-03-11 16:40:00 EST  │
│ 2022-03-11 16:45:00 UTC ┆ 2022-03-11 16:45:00 EST  │
│ 2022-03-11 16:50:00 UTC ┆ 2022-03-11 16:50:00 EST  │
│ 2022-03-11 16:55:00 UTC ┆ 2022-03-11 16:55:00 EST  │
└─────────────────────────┴──────────────────────────┘

EDIT

从 Polars 0.16.15 开始,您可以使用.dt.time:

In [12]: tz_replaced_filtered = tdf.with_columns(
    ...:     pl.col("UTC").dt.replace_time_zone(time_zone="US/Eastern").alias("NY")
    ...: ).filter(
    ...:   pl.col("NY").dt.time().is_between(time(9), time(16), closed="both")
    ...: )

In [13]: tz_replaced_filtered
Out[13]:
shape: (5780, 2)
┌─────────────────────────┬──────────────────────────┐
│ UTC                     ┆ NY                       │
│ ---                     ┆ ---                      │
│ datetime[ns, UTC]       ┆ datetime[ns, US/Eastern] │
╞═════════════════════════╪══════════════════════════╡
│ 2022-01-03 09:00:00 UTC ┆ 2022-01-03 09:00:00 EST  │
│ 2022-01-03 09:05:00 UTC ┆ 2022-01-03 09:05:00 EST  │
│ 2022-01-03 09:10:00 UTC ┆ 2022-01-03 09:10:00 EST  │
│ 2022-01-03 09:15:00 UTC ┆ 2022-01-03 09:15:00 EST  │
│ …                       ┆ …                        │
│ 2022-03-11 15:45:00 UTC ┆ 2022-03-11 15:45:00 EST  │
│ 2022-03-11 15:50:00 UTC ┆ 2022-03-11 15:50:00 EST  │
│ 2022-03-11 15:55:00 UTC ┆ 2022-03-11 15:55:00 EST  │
│ 2022-03-11 16:00:00 UTC ┆ 2022-03-11 16:00:00 EST  │
└─────────────────────────┴──────────────────────────┘
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Polars的replace_time_zone和convert_time_zone对于相同的时区转换显示不同的字符串表示形式 的相关文章

  • Python 类型提示 Dict 语法错误 可变默认值是不允许的。使用“默认工厂”

    我不知道为什么解释器会抱怨这个类型的字典 对于这两个实例 我得到一个 不允许可变默认值 使用默认工厂 语法错误 我使用的是 python 3 7 3 from dataclasses import dataclass from typing
  • 计算另一个字符串中多个字符串的出现次数

    在 Python 2 7 中 给定以下字符串 Spot是一只棕色的狗 斑点有棕色的头发 斑点的头发是棕色的 查找字符串中 Spot brown 和 hair 总数的最佳方法是什么 在示例中 它将返回 8 我正在寻找类似的东西string c
  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • matplotlib 图中点的标签

    所以这是一个关于已发布的解决方案的问题 我试图在我拥有的 matplotlib 散点图中的点上放置一些数据标签 我试图在这里模仿解决方案 是否有与 MATLAB 的 datacursormode 等效的 matplotlib https s
  • 多输出堆叠回归器

    一次性问题 我正在尝试构建一个多输入堆叠回归器 添加到 sklearn 0 22 据我了解 我必须结合StackingRegressor and MultiOutputRegressor 经过多次尝试 这似乎是正确的顺序 import nu
  • 从Django中具有外键关系的两个表中检索数据? [复制]

    这个问题在这里已经有答案了 This is my models py file from django db import models class Author models Model first name models CharFie
  • 打印数字时添加千位分隔符[重复]

    这个问题在这里已经有答案了 我真的不知道这个问题的 名称 所以它可能是一个不正确的标题 但问题很简单 如果我有一个数字 例如 number 23543 second 68471243 我想要它使print 像这样 23 54368 471
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 如何将特定范围内的标量添加到 numpy 数组?

    有没有一种更简单 更节省内存的方法可以单独在 numpy 中执行以下操作 import numpy as np ar np array a l r ar c a a 0 l ar tolist a r 它可能看起来很原始 但它涉及获取给定数
  • 使用 python/numpy 重塑数组

    我想重塑以下数组 gt gt gt test array 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 为了得到 gt gt gt test2 array 11 12 21 22 13 14
  • 未知错误:Chrome 无法启动:异常退出

    当我使用 chromedriver 对 Selenium 运行测试时 出现此错误 selenium common exceptions WebDriverException Message unknown error Chrome fail
  • Django 视图中的“请求”是什么

    在 Django 第一个应用程序的 Django 教程中 我们有 from django http import HttpResponse def index request return HttpResponse Hello world
  • 如何将 ascii 值列表转换为 python 中的字符串?

    我在 Python 程序中有一个列表 其中包含一系列数字 这些数字本身就是 ASCII 值 如何将其转换为可以在屏幕上回显的 常规 字符串 您可能正在寻找 chr gt gt gt L 104 101 108 108 111 44 32 1
  • Django REST Framework - CurrentUserDefault 使用

    我正在尝试使用CurrentUserDefault一个序列化器的类 user serializers HiddenField default serializers CurrentUserDefault 文档说 为了使用它 请求 必须作为
  • 找到一个数字所属的一组范围

    我有一个 200k 行的数字范围列表 例如开始位置 停止位置 该列表包括除了非重叠的重叠之外的所有类型的重叠 列表看起来像这样 3 5 10 30 15 25 5 15 25 35 我需要找到给定数字所属的范围 并对 100k 个数字重复该
  • Javascript转换时区问题

    我在转换当前时区的日期时间时遇到问题 我从服务器收到此日期字符串 格式为 2015 10 09T08 00 00 这是中部时间 但是当我使用 GMT 5 中的 new Date strDate 转换此日期时间时 它返回给我的信息如下 这是不
  • 条件在反应本机生产中失败,但在开发中有效

    我创建了一个反应本机应用程序 我需要通过它进行比较 如果属实 就会执行死刑 问题是 该条件适用于 React Native 开发模式 而不适用于 React Native 生产版本 我使用 firebase 作为数据库 也使用 redux
  • 根据 Pandas 中的列表选择数据框行的子集

    我有一个数据框df1并列出x In 22 import pandas as pd In 23 df1 pd DataFrame C range 5 B range 10 20 2 A list abcde In 24 df1 Out 24
  • 如何使用 PrimaryKeyRelatedField 更新多对多关系上的类别

    Django Rest 框架有一个主键相关字段 http www django rest framework org api guide relations primarykeyrelatedfield其中列出了我的 IDmany to m
  • JSON:TypeError:Decimal('34.3')不是JSON可序列化的[重复]

    这个问题在这里已经有答案了 我正在运行一个 SQL 查询 它返回一个小数列表 当我尝试将其转换为 JSON 时 出现类型错误 查询 res db execute SELECT CAST SUM r SalesVolume 1000 0 AS

随机推荐