Pandas - 写实木复合地板并将列保持为十进制
Posted
技术标签:
【中文标题】Pandas - 写实木复合地板并将列保持为十进制【英文标题】:Pandas - Write parquet and keep column as Decimal 【发布时间】:2019-06-27 02:01:56 【问题描述】:我正在尝试将 parquet 文件写入 s3 以运行 Copy into Redshift/Parquet 文件正在正确写入,但尝试复制时出现错误:Column type: DECIMAL(10,2), Parquet schema: optional doubl
。
错误消息很清楚,但我不确定如何强制将列设为Decimal
类型。
有可能吗?写 parquet 时保持列 value
为十进制?
from datetime import datetime
import pandas as pd
import decimal as D
import numpy as np
data = [
"name": "ted",
"timestamp": datetime.now().isoformat(),
"actual_data": "2019-06-28 00:00:00",
"age": 34,
"value": 0.10
,
"name": "barney",
"timestamp": datetime.now().isoformat(),
"actual_data": "2019-06-28 10:00:00",
"age": 35,
]
df = pd.DataFrame.from_dict(data,)
df['age'] = df['age'].astype(int)
df['value'] = df['value'].fillna(0)
df['value'] = df['value'].astype(np.float, 2)
# df_merged["id"] = df_merged["id"].astype(int)
print(df)
df.to_parquet(f"s3://awesome-parquet-test/data.parquet", index=False)
【问题讨论】:
【参考方案1】:要将列作为十进制值写入 Parquet,它们需要以十进制开头。
您的数据框中的值(此处为示例简化了一点)是浮点数,因此它们被写为浮点数:
>>> df = pd.DataFrame('value': [0.1, 0.0])
>>> df
value
0 0.1
1 0.0
>>> df['value'].dtype
dtype('float64')
>>> df.to_parquet("test_data.parquet", index=False)
>>> pq.read_metadata("test_data.parquet").schema
<pyarrow._parquet.ParquetSchema object at 0x7f07248334a8>
value: DOUBLE
但是当我们第一次在 Python 中将浮点数转换为小数时,我们实际上可以将小数写入 Parquet:
>>> import decimal
>>> df['value_decimal'] = df['value'].astype(str).map(decimal.Decimal)
>>> df['value_decimal'].values
array([Decimal('0.1'), Decimal('0.0')], dtype=object)
>>> df.to_parquet("test_data.parquet", index=False)
>>> pq.read_metadata("test_data.parquet").schema
<pyarrow._parquet.ParquetSchema object at 0x7f073ae52898>
value: DOUBLE
value_decimal: FIXED_LEN_BYTE_ARRAY DECIMAL
对于Python中的小数转换:我首先转换成字符串的原因是因为否则小数会使用浮点的全精度(导致超过10个小数)
【讨论】:
在df['value_decimal'] = df['value'].astype(str).map(decimal.Decimal)
行中如何指定像 Decimal(18) 这样的精度。谢谢!
getcontext().prec = <precision>
df['value_decimal'] = df['value'].astype(str).map(decimal.Decimal)
谢谢!我用它来解决其他问题:***.com/questions/61421702/…
我不喜欢字符串步骤,所以我选择了df['value_decimal'] = df['value'].map(decimal.Decimal).map(lambda x: round(x,2))
这也解决了指定精度问题。以上是关于Pandas - 写实木复合地板并将列保持为十进制的主要内容,如果未能解决你的问题,请参考以下文章
pandas把dataframe的数据列转化为索引列实战:单列转化为索引多列转化为复合索引
pandas读取csv数据参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用set_index函数把数据列转化为行索引(keys参数指定需要被转化的数据列)
pandas读取csv数据参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用set_index函数把数据列转化为行索引(keys参数指定需要被转化的数据列)
Pandas中xs()函数索引复合索引数据的不同切面数据(索引复合索引中需要的数据):索引列复合索引中的一个切面索引行复合索引中的一个切面
pandas读取csv数据header参数指定作为列索引的行索引列表形成复合(多层)列索引使用reset_index函数把行索引重置为列数据(level参数设置将原行索引中的指定层转化为列数据)