You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas read_csv的parse_dates未限制指定列,如何修复?

问题:CSV读取时时间列转换导致非时间列数据损坏

问题场景

读取CSV文件时,需要仅将指定时间列转换为纪元秒数,但现有代码错误地将转换逻辑应用到所有列,导致价格等数值列被损坏(如44.68这类原始值丢失)。

原代码

import pandas as pd


TIME_STG = "Datum (UTC)"
PRICE_STG = "Day Ahead Auktion (DE-LU)"
PRICE_FILE = "booking_algorythm/data/energy-charts_Stromproduktion_und_Börsenstrompreise_in_Deutschland_2021.csv"

def get_data(file, *columns):
    types_dict = {}
    parse_dates_list = []
    for column in columns:
        if column == TIME_STG:
            types_dict.update({column: str})
            parse_dates_list.append(column)
        else:
            types_dict.update({column: float})
    data = pd.read_csv(file,
                       sep=",",
                       usecols=columns,
                       dtype=types_dict,
                       parse_dates=parse_dates_list,
                       date_parser=lambda col: pd.to_datetime(col, utc=True)).astype(int) // 10**9
    data_np = data.to_numpy()
    return data_np

def get_price_vector():
    data = get_data(PRICE_FILE, PRICE_STG, TIME_STG)
    return data

def main():
    vector = get_price_vector()
    print(vector)

if __name__ == "__main__":
    main()

示例CSV数据

"Datum (UTC)","Kernenergie","Nicht Erneuerbar","Erneuerbar","Last","Day Ahead Auktion (DE-LU)"
2021-01-01T00:00:00.000Z,8151.12,35141.305,11491.71,43516.88,48.19
2021-01-01T00:15:00.000Z,8147.209,34875.902,11331.25,42998.01,48.19
2021-01-01T00:30:00.000Z,8154.02,34825.553,11179.375,42494.2,48.19
2021-01-01T00:45:00.000Z,8152.82,34889.11,11072.377,42320.32,48.19
2021-01-01T01:00:00.000Z,8156.53,34922.123,10955.356,41598.39,44.68
2021-01-01T01:15:00.000Z,8161.601,34856.2,10867.771,41214.32,44.68
2021-01-01T01:30:00.000Z,8158.36,35073.1,10789.049,40966.95,44.68
2021-01-01T01:45:00.000Z,8151.3,34972.501,10657.209,40664.63,44.68
2021-01-01T02:00:00.000Z,8145.589,34911.037,10637.605,40502.78,42.92

问题根源

原代码中.astype(int) // 10**9是对整个DataFrame执行操作,会把价格列的浮点值强制转为整数再除以1e9,直接破坏了原始价格数据。

解决方案

仅对时间列执行纪元秒数转换,其他列保留原有类型:

修改后的代码

import pandas as pd


TIME_STG = "Datum (UTC)"
PRICE_STG = "Day Ahead Auktion (DE-LU)"
PRICE_FILE = "booking_algorythm/data/energy-charts_Stromproduktion_und_Börsenstrompreise_in_Deutschland_2021.csv"

def get_data(file, *columns):
    types_dict = {}
    parse_dates_list = []
    for column in columns:
        if column == TIME_STG:
            types_dict.update({column: str})
            parse_dates_list.append(column)
        else:
            types_dict.update({column: float})
    # 正常读取数据,不对整个DF做类型转换
    data = pd.read_csv(file,
                       sep=",",
                       usecols=columns,
                       dtype=types_dict,
                       parse_dates=parse_dates_list,
                       date_parser=lambda col: pd.to_datetime(col, utc=True))
    # 仅转换时间列为纪元秒数(两种方式二选一即可)
    # 方式1:利用datetime64纳秒存储特性转换
    data[TIME_STG] = (data[TIME_STG].astype(int) // 10**9)
    # 方式2:更直观的timestamp方法
    # data[TIME_STG] = data[TIME_STG].apply(lambda x: x.timestamp())
    data_np = data.to_numpy()
    return data_np

def get_price_vector():
    data = get_data(PRICE_FILE, PRICE_STG, TIME_STG)
    return data

def main():
    vector = get_price_vector()
    print(vector)

if __name__ == "__main__":
    main()

说明

  1. 先完成CSV读取和时间列解析,得到包含datetime类型时间列、浮点类型价格列的DataFrame
  2. 单独对TIME_STG列执行纪元秒数转换,两种方式均可:
    • 原方法:利用datetime64的纳秒存储特性,转整数后除以1e9得到秒数
    • timestamp()方法:直接调用pd.Timestamp的内置方法获取纪元秒数,可读性更强
  3. 价格等其他列保持原始浮点类型,不会被修改
  4. 最终转为numpy数组返回时,价格列保留48.19、44.68等原始值,时间列转为正确的纪元秒数

内容的提问来源于stack exchange,提问作者Andreas Schuldei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:35:12