我想从一个亚秒精度的TimeSeries.csv文件的一列中解析时间,但对于一些时间戳,它返回NaT.

该数据集的一个奇怪之处在于,每一非整秒将以%Y-%m-%d %H:%M:%S.%f表示,而每一整秒将以%Y-%m-%d %H:%M:%S表示

我观察到,格式将在第一行将被转换,其他将是NaT

例如:

import pandas as pd

# Example data
timestamps_full_first = [
    "2023-12-30 00:00:00",
    "2023-12-30 00:00:00.1",
    "2023-12-30 00:00:00.9",
    "2023-12-30 00:00:01"
]

timestamps_sub_first = [
    "2023-12-30 00:00:00.1",
    "2023-12-30 00:00:00.9",
    "2023-12-30 00:00:01",
    "2023-12-30 00:00:01.1"
]

# Convert to datetime
datetime_series_full_first = pd.to_datetime(timestamps_full_first, errors='coerce', utc=True)
datetime_series_sub_first = pd.to_datetime(timestamps_sub_first, errors='coerce', utc=True)
print(datetime_series_full_first)
print(datetime_series_sub_first)

输出:

DatetimeIndex(['2023-12-30 00:00:00+00:00', 'NaT', 'NaT',
               '2023-12-30 00:00:01+00:00'],
              dtype='datetime64[ns, UTC]', freq=None)
DatetimeIndex(['2023-12-30 00:00:00.100000+00:00',
               '2023-12-30 00:00:00.900000+00:00',
                                            'NaT',
               '2023-12-30 00:00:01.100000+00:00'],
              dtype='datetime64[ns, UTC]', freq=None)

Initial Solution

我最初的解决方案是编写一个定制的parse_date函数,我可以在其中以列表的形式提供多种格式.

def parse_date(self, date_str, formats = ["none"]):
            for fmt in formats:
                try:
                    return pd.to_datetime(date_str, format=fmt, utc=True)
                except ValueError:
                    continue
            return pd.NaT  # Return 'Not a Time' for unrecognized formats

用途:

data[self.timestamp_col] = data[self.timestamp_col].apply(lambda x: self.parse_date(x, formats = self.timestamp_formats))

它是有效的,但与Pandas 的内部解析相比,它非常非常慢.

Optimized Solution(GPT-4建议):

GPT建议将数据帧矢量化,然后使用掩码进行一次解析,然后使用另一种格式解析每秒包含NaT行的行,这应该会提高性能.

import pandas as pd
import numpy as np

def vectorized_parse_date(date_series, formats):
    result_series = pd.Series(np.full(date_series.shape, pd.NaT), index=date_series.index)
    for fmt in formats:
        mask = result_series.isna() & ~date_series.isna()  # Only try to parse where we don't have a result and the date is not NaN
        try:
            result_series[mask] = pd.to_datetime(date_series[mask], format=fmt, errors='raise', utc=True)
        except ValueError:
            continue
    return result_series

# Usage
data[self.timestamp_col] = vectorized_parse_date(data[self.timestamp_col], formats=self.timestamp_formats)

我还没有试过,因为我觉得GPT对我的方法有点偏见,试图弄清楚如何在我的人为约束下做到这一点.

所以也许你们中的一些人看到了另一个使用pandas功能的解决方案.

推荐答案

如果我设置为format="ISO8601"(pandas v2功能),对我来说很好-我想说ISO 8601是对输入格式最精确的描述.

datetime_series_full_first = pd.to_datetime(timestamps_full_first, format="ISO8601", 
                                            utc=True, errors='coerce')
datetime_series_sub_first = pd.to_datetime(timestamps_sub_first, format="ISO8601",  
                                           utc=True, errors='coerce')
print(datetime_series_full_first)
print(datetime_series_sub_first)

DatetimeIndex([       '2023-12-30 00:00:00+00:00',
               '2023-12-30 00:00:00.100000+00:00',
               '2023-12-30 00:00:00.900000+00:00',
                      '2023-12-30 00:00:01+00:00'],
              dtype='datetime64[ns, UTC]', freq=None)
DatetimeIndex(['2023-12-30 00:00:00.100000+00:00',
               '2023-12-30 00:00:00.900000+00:00',
                      '2023-12-30 00:00:01+00:00',
               '2023-12-30 00:00:01.100000+00:00'],
              dtype='datetime64[ns, UTC]', freq=None)

Python相关问答推荐

将特定列信息移动到当前行下的新行

连接两个具有不同标题的收件箱

ModuleNotFound错误:没有名为Crypto Windows 11、Python 3.11.6的模块

如何找到满足各组口罩条件的第一行?

管道冻结和管道卸载

如何使用数组的最小条目拆分数组

cv2.matchTemplate函数匹配失败

当递归函数的返回值未绑定到变量时,非局部变量不更新:

计算天数

如何更新pandas DataFrame上列标题的de值?

Python—转换日期:价目表到新行

导入错误:无法导入名称';操作';

比Pandas 更好的 Select

为用户输入的整数查找根/幂整数对的Python练习

Django.core.exceptions.SynchronousOnlyOperation您不能从异步上下文中调用它-请使用线程或SYNC_TO_ASYNC

我怎么才能用拉夫分拣呢?

Django抛出重复的键值违反唯一约束错误

BeatuifulSoup从欧洲志愿者服务中获取数据和解析:一个从EU-Site收集机会的小铲子

将相应的值从第2列合并到第1列(Pandas )

对当前的鼹鼠进行编码,并且我的按键获得了注册