pandas.to_parquet pyarrow.lib.ArrowInvalid:无法转换 Timedelta

问题描述 投票:0回答:1

我有一个巨大的长格式多索引数据框。只有一个“值”列。 “value”中的某些条目的类型为

pd.Timedelta

尝试使用

parquet
将该数据帧另存为
pd.to_parquet
文件时出现错误:

pyarrow.lib.ArrowInvalid: ("Could not convert Timedelta('2903 days 00:00:00') with type Timedelta: tried to convert to double", 'Conversion failed for column value with type object')

如果我将错误消息中的特定值转换为

numpy
,我会得到以下信息:

array([Timedelta('2903 days 00:00:00')], dtype=object)

我设置了一个玩具示例来检查是否可以将

pd.Timedelta
转换为
parquet
。下面的代码工作得很好:

import pandas as pd

idx = pd.MultiIndex.from_tuples(
    [("A", "x"), ("A", "y"), ("B", "x"), ("B", "y")],
    names=["idx1", "idx2"])
data = {"value": [
    pd.Timedelta(days=10),
    2.5,
    pd.Timedelta(days=20),
    5
]}

df = pd.DataFrame(data=data, index=idx)
df.to_parquet("test.parquet")

x = pd.read_parquet("test.parquet")

一个简单的

df.iloc[0, :].to_numpy()
提供与我的真实数据框中完全相同的类型:
array([Timedelta('10 days 00:00:00')], dtype=object)

我想知道我的原始数据框与我的玩具示例相比可能有什么区别?

python pandas parquet pyarrow
1个回答
0
投票

这部分错误

'Conversion failed for column value with type object'
表明您的列是浮点数和时间增量的混合体,正如您所期望的那样。

问题来自于这样一个事实:当你有一个大数据框时,pyarrow 会从 pandas 数据框的第一行推断出类型。最有可能在你的情况下它们都是花车。此代码(与您的示例相同但稍作修改)将重现您的错误:

import pandas as pd

float_vals = [2.5 for i in range(10000)]
float_index_val = [("float", i) for i in range(10000)]
float_vals.extend([("A", "x"), ("A", "y"), ("B", "x"), ("B", "y")])
float_vals.extend([
    pd.Timedelta(days=2903),
    2.5,
    pd.Timedelta(days=20),
    5
])

idx = pd.MultiIndex.from_tuples(
    float_vals,
    names=["idx1", "idx2"])
data = {"value": float_vals}

df = pd.DataFrame(data=data, index=idx)
df.to_parquet("test.parquet")

x = pd.read_parquet("test.parquet")

这里的问题是镶木地板中的一列不能有多种类型。在您的示例中,如果您加载保存的镶木地板,您将看到所有内容都已转换为 timedelta。例如

x = pd.read_parquet("test.parquet")
随后是
x.iloc[1, :].to_numpy()
提供此
array([2], dtype='timedelta64[us]')

如果浮点值不代表增量时间,您应该按照注释的建议进行操作并对数据进行逆透视。如果浮点值表示增量时间,您可以在保存之前对其进行转换,或者在保存时传递模式。

df.value = pd.to_timedelta(df.value)
df.to_parquet("test.parquet")

df.to_parquet("test.parquet", schema=pa.schema([("value", pa.duration("s"))]))
© www.soinside.com 2019 - 2024. All rights reserved.