在包含Null的int列上推断架构的Parquet问题

时间:2019-08-30 05:07:19

标签: pandas amazon-s3 parquet pyarrow

我正在阅读s3键,并使用熊猫将其转换为实木复合地板。在转换成实木复合地板之前,我先进行类型转换,以便pyarrow可以正确推断出架构。

该代码段如下所示:

df = pd.read_csv(io.BytesIO(s3.get_object(Bucket=s3_bucket, Key=s3_key)['Body'].read()), sep='\t', error_bad_lines=False, warn_bad_lines=True)

df['col_name'] = df['col_name'].astype('int')

table = pa.Table.from_pandas(df)
buf = pa.BufferOutputStream()
pq.write_table(table, buf, compression='snappy')

到目前为止很好。

问题是,当int列具有空值时,pandas会将其作为对象偏离。有什么办法可以将其转换为“ int”。一种方法是先执行fillna(0)或使用99999,然后进行类型转换。它起作用了,但是Null和0或99999在该列中具有不同的含义。

那么有什么主意如何将其转换为int类型?或我可以做些什么来修改上面的代码来处理这种情况?

1 个答案:

答案 0 :(得分:0)

从熊猫文档中:

  

因为NaN是浮点数,所以一列甚至有一个缺失值的整数都将转换为浮点dtype

从0.24版开始,存在一些扩展的整数类型,它们能够保存缺失值。转换为dtype="Int64"

您可以在下面找到更多信息 https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html

编辑:箭头中建议的解决方法是

import pandas as pd
import pyarrow as pa


def from_pandas(df):
    """Cast Int64 to object before 'serializing'"""
    for col in df:
        if isinstance(df[col].dtype, pd.Int64Dtype):
            df[col] = df[col].astype('object')
    return pa.Table.from_pandas(df)


def to_pandas(tbl):
    """After 'deserializing', recover the correct int type"""
    df = tbl.to_pandas(integer_object_nulls=True)

    for col in df:
        if (pa.types.is_integer(tbl.schema.field_by_name(col).type) and
            pd.api.types.is_object_dtype(df[col].dtype)):
                df[col] = df[col].astype('Int64')

    return df


df = pd.Series([0, 1, None, 2, 822215679726100500], dtype='Int64', name='x').to_frame()
# df = pd.Series([0, 1, 3, 2, 822215679726100500], dtype='Int64', name='x').to_frame()
# df = pd.Series([0, 1, 3, 2, 15], dtype='Int64', name='x').to_frame()
# df = pd.Series([0, 1, 3, 2, 15], dtype='int16', name='x').to_frame()

df2 = to_pandas(from_pandas(df))    
df2.dtypes

Thomas Buhrmann的所有积分