war*_*ckh 5 python pandas pyarrow
我有一个非常宽的数据框(20,000 列),主要由 Pandas 中的 float64 列组成。我想将这些列转换为 float32 并写入 Parquet 格式。我这样做是因为这些文件的下游用户是内存有限的小容器。
我目前在 Pandas 中投射,但这在广泛的数据集上非常慢,然后写出镶木地板。是否可以在写入 to_parquet 过程本身时转换类型?下面显示了一个虚拟示例。
import pandas as pd
import numpy as np
import pyarrow
df = pd.DataFrame(np.random.randn(3000, 15000)) # make dummy data set
df.columns = [str(x) for x in list(df)] # make column names string for parquet
df[list(df.loc[:, df.dtypes == float])] = df[list(df.loc[:, df.dtypes == float])].astype('float32') # cast the data
df.to_parquet("myfile.parquet") # write out the df
Run Code Online (Sandbox Code Playgroud)
Krz*_*ski 11
使用 pandas 1.0.x 和 pyarrow 0.15+ 可以使用本文中的模式定义在 to_parquet 中传递模式参数,如下所示。输入 pyarrow 以用于模式定义。
import pandas as pd
import pyarrow as pa
FILE_PATH = "/tmp/df.parquet"
df = pd.DataFrame({'a': [None, None]})
df.to_parquet(FILE_PATH)
pd.read_parquet(FILE_PATH).dtypes
Run Code Online (Sandbox Code Playgroud)
这给出了以下类型:
a object
dtype: object
Run Code Online (Sandbox Code Playgroud)
定义模式后:
SCHEMA = pa.schema([('a', pa.int32())])
df.to_parquet(FILE_PATH, schema=SCHEMA)
pd.read_parquet(FILE_PATH).dtypes
Run Code Online (Sandbox Code Playgroud)
它现在给出以下类型:
a float64
dtype: object
Run Code Online (Sandbox Code Playgroud)
尝试使用箭头而不是 pandas 进行向下转换:
def convert_arrow(df):
table = pa.Table.from_pandas(df)
columns = [
c.cast(pa.float32()) if c.type == pa.float64() else c
for c in table
]
return pa.Table.from_arrays(columns, table.column_names)
Run Code Online (Sandbox Code Playgroud)
我做了一个简单的基准测试,速度快了 20 倍。
我认为您的代码的问题在于,在现有的 DataFrmae 中一一分配列,这效率不高。这篇博文解释得很好:https://uwekorn.com/2020/05/24/the-one-pandas-internal.html
另一个不涉及箭头的简单解决方案是转换每列并在最后创建数据框。下面的代码比箭头版本稍慢:
def convert_pandas_by_columns(df):
columns = [
df[c].astype('float32') if df[c].dtype == float else df[c]
for c in df.columns
]
return pd.DataFrame(columns)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1467 次 |
| 最近记录: |