提问人:doplano 提问时间:10/27/2023 最后编辑:doplano 更新时间:10/30/2023 访问量:27
稀疏 Pandas 数据帧 goupby sum 强制转换为 float32
Sparse Pandas dataframe goupby sum enforce casting to float32
问:
鉴于:
import pandas as pd
import numpy as np
def get_random_df(row:int=10, col:int=7): # generate random Sparse Pandas dataframe
np.random.seed(0)
d=np.random.randint(low=0, high=10, size=(row,col)).astype(np.float32)
d[d < 4] = np.nan
df=pd.DataFrame(data=d,
index=[f"ip{i}" for i in np.random.choice(range(max(row, 10)), row, replace=False) ],
columns=[f"col_{c}" for c in np.random.choice(range(max(col, 10)), col, replace=False) ],
dtype=pd.SparseDtype(dtype=np.float32),)
df.index.name='usr'
return df
def get_concat(pdfs): # pdfs=[df1, df2,..., dfN]
dfc=pd.concat(pdfs, axis=0, sort=True) # sort=True: sort columns
dfc=dfc.astype(pd.SparseDtype(dtype=np.float32, fill_value=np.nan)) # after concat, there's still NaNs
dfc=dfc.groupby(level=0) # groupby index: 'usr'
dfc=dfc.sum(engine="numba", engine_kwargs={'nopython': True, 'parallel': True, 'nogil': False}) # original SUM dtypes: float64 NOT SPARSE! =>> problem!!
dfc=dfc.astype(pd.SparseDtype(dtype=np.float32, fill_value=0.0))# after sum, we get 0s
dfc=dfc.sort_index(key=lambda x: ( x.to_series().str[2:].astype(int) )) # customized sorting of indices: ip1, ip2, ip12, ...
dfc=dfc.astype(pd.SparseDtype(dtype=np.float32, fill_value=0.0))
return dfc
我想连接几个非常大的稀疏 pandas 数据帧。作为连接两个相当大的稀疏随机 pandas 数据帧的示例:
df1=get_random_df(row=np.random.randint(low=2e3, high=5e3), col=np.random.randint(low=1e6, high=4e6))
df2=get_random_df(row=np.random.randint(low=2e3, high=3e3), col=np.random.randint(low=1e6, high=5e6))
df_concat=get_concat(pdfs=[df1, df2])
我注意到函数返回中的方法非常耗时且占用大量内存。sum()
get_concat
float64
我使用引擎来使并行化受益,从而加快实现速度,因为默认引擎没有完成此示例示例。numba
sum()
我可以使用强制转换类型,但由于它是按顺序执行的,因此我会遇到较大尺寸的内存问题。以下是我的实现摘要:astype
pd.concat => cast (Sparse float32) => groupby => sum() => cast (Sparse float32) => sort index => cast (Sparse float32)
并分别详细打印每个部分:
elapsed_time [concat+float32] 1392.3 sec
<class 'pandas.core.frame.DataFrame'>
Index: 7006 entries, ip2611 to ip626
Columns: 4191807 entries, col_0 to col_999999
dtypes: Sparse[float32, nan](4191807)
memory usage: 122.9 GB
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
elapsed_time [groupby] 0.0010 sec
elapsed_time [sum] 4529.3 sec
Current : 138035.44 MB | Peak: 417264.41 MB
<class 'pandas.core.frame.DataFrame'>
Index: 4315 entries, ip0 to ip999
Columns: 4191807 entries, col_0 to col_999999
dtypes: float64(4191807) # <<<<<<<< Problem >>>>>>>>>
memory usage: 134.8 GB # <<<<<<<< Large Memroy >>>>>>>>>
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
elapsed_time [=> float32 sparsity: 0.71] 3040.4 sec
Current : 101547.83 MB | Peak: 254647.26 MB
<class 'pandas.core.frame.DataFrame'>
Index: 4315 entries, ip0 to ip999
Columns: 4191807 entries, col_0 to col_999999
dtypes: Sparse[float32, 0.0](4191807)
memory usage: 95.8 GB
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
elapsed_time [sort_idx+float32] 3178.5 sec
Current : 101547.83 MB | Peak: 254647.26 MB
<class 'pandas.core.frame.DataFrame'>
Index: 4315 entries, ip0 to ip4314
Columns: 4191807 entries, col_0 to col_999999
dtypes: Sparse[float32, 0.0](4191807)
memory usage: 95.8 GB
是否有任何其他有效的替代方法可以强制执行以直接获取结果以降低内存消耗,或者这是一种完全错误的方法?sum()
float32
答: 暂无答案
评论
O(sqrt(n))
O(log n)
sum
float32
float32