我需要处理相当大的数据框架~80M条记录,本质上内存消耗是一个问题。因此,包含数值数据的列将收缩到可能的最小dtype,如np.int8,np.int16,np.int32。在某个阶段,我需要使用现有列的一些数学计算新列,它需要int64的容量。大多数Pandas算术构造失败的地方。我花了一段时间才发现原因是整数溢出:简而言之,计算
newCol = col16*col16,
newCol = col32*value16,
尽管newCol创建为int64,但通常会产生不正确的结果。以下是一些简单显式示例:计算newCol = A * 100000
,显然对于任何A=aaaaa
都应该计算出类似aaaaa00000
的值。
但是,请参见下文:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(1<<7,1<<15, size=(int(5))), columns=list('A'), dtype=np.int16)
df.eval('Q = A * 100000', inplace=True) # 1st naive approach from a head
df['W'] = df['A'] * 100000
# trying to use const c=int64() to force expr evaluator to use int64
c = np.int64(10000)
df.eval('R = @c * A', inplace=True)
# trying to create new int64 col 1st and use it in calc:
df['T']=0 # this creates new col 'T' dtype=int64 filled with 0
df.eval('T = 100000 * A', inplace=True)
df['S']=0
# trying to force int64 via 1st element 'S', which is int64
df['S'] = df['S'] + df['A'] * 100000
# here finally this approach works, calculation is using int64 instructions:
df['X']=1
df.eval('X = X * 100000 * A', inplace=True)
# just preformatting
pd.set_option('display.max_columns', None)
pd.options.display.width=222
df.index=[''] * len(df)
print(df)
df.info()
A Q W R T S X
3396 339600000 339600000 339600000 339600000 339600000 339600000
26508 -1644167296 -1644167296 -1644167296 -1644167296 -1644167296 2650800000
27942 -1500767296 -1500767296 -1500767296 -1500767296 -1500767296 2794200000
3441 344100000 344100000 344100000 344100000 344100000 344100000
27880 -1506967296 -1506967296 -1506967296 -1506967296 -1506967296 2788000000
<class 'pandas.core.frame.DataFrame'>
Index: 5 entries, to
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 5 non-null int16
1 Q 5 non-null int32
2 W 5 non-null int32
3 R 5 non-null int32
4 T 5 non-null int64
5 S 5 non-null int64
6 X 5 non-null int64
dtypes: int16(1), int32(3), int64(3)
memory usage: 230.0+ bytes
用6种不同的方法来完成琐碎的数学运算,只有col 'X'产生了我(我猜大多数用户)所期望的。
一个明显的解决方法是,首先将源列的dtype转换为int64(就像“在飞行中”一样),如
df['x'] = df['A'].astype(np.int64) * 100000
但我不认为这是一个很好的解决方案在我的情况下,因为数据已经是大到创建一个更大的tmp副本,性能也将下降冗余转换。
所以我的问题是如何在运行中计算它,而不是在int64中创建整个源数据列的副本(没有RAM),例如在64位CPU中直接正确计算newCol64 = srcCol8 * srcCol16 * srcCol16
。pandas.eval()
是否存在显式类型转换语法?在逐行计算结果时可以动态地完成哪些操作?
1条答案
按热度按时间ogsagwnx1#
如果将数组乘以标量值,则选定的dtype将是该数组的dtype。然而,如果你在两个数组之间做一个数学运算,比如
X
(X * A),数组将被“向上转换”:您可以阅读有关输出类型确定的文档。
在您的情况下,您可以:
输出: