我遇到的问题是数据集有400,000行和300个变量。我必须为具有3,000多个不同项目的分类变量获取虚拟变量。最后,我想得到一个包含3,300个变量或特征的数据集,以便我可以训练一个RandomForest模型。
以下是我尝试过的事情:
df = pd.concat([df, pd.get_dummies(df['itemID'],prefix = 'itemID_')], axis=1)
当我这样做时,我总会得到一个内存错误。我可以拥有的变量数量是否有限制?
如果我只使用前1000行(有374个不同类别),那就可以了。
有没有人能解决我的问题?我正在使用的计算机有8 GB的内存。
答案 0 :(得分:23)
更新:从版本0.19.0开始,get_dummies返回一个8位整数而不是64位浮点数,这将在许多情况下解决此问题,并使下面的as_type
解决方案变得不必要。请参阅:get_dummies -- pandas 0.19.0
但在其他情况下,下面提到的sparse
选项可能仍然有用。
原始答案:以下是尝试的几种可能性。两者都会大幅减少数据帧的内存占用,但您以后仍可能遇到内存问题。很难预测,你只需要尝试。
(请注意,我正在简化下面info()
的输出)
df = pd.DataFrame({ 'itemID': np.random.randint(1,4,100) })
pd.concat([df, pd.get_dummies(df['itemID'],prefix = 'itemID_')], axis=1).info()
itemID 100 non-null int32
itemID__1 100 non-null float64
itemID__2 100 non-null float64
itemID__3 100 non-null float64
memory usage: 3.5 KB
这是我们的基线。每个虚拟列占用800个字节,因为样本数据有100行,get_dummies
似乎默认为float64(8个字节)。这似乎是一种不必要的低效方式来存储虚拟对象,因为你可以尽可能少地使用它,但可能有一些我不知道的原因。
所以,首先尝试,只需更改为一个字节的整数(这似乎不是get_dummies
的选项,因此必须使用astype(np.int8)
进行转换。
pd.concat([df, pd.get_dummies(df['itemID'],prefix = 'itemID_').astype(np.int8)],
axis=1).info()
itemID 100 non-null int32
itemID__1 100 non-null int8
itemID__2 100 non-null int8
itemID__3 100 non-null int8
memory usage: 1.5 KB
每个虚拟列现在占用内存的1/8。
或者,您可以使用sparse
的{{1}}选项。
get_dummies
相当可观的节省。 pd.concat([df, pd.get_dummies(df['itemID'],prefix = 'itemID_',sparse=True)],
axis=1).info()
itemID 100 non-null int32
itemID__1 100 non-null float64
itemID__2 100 non-null float64
itemID__3 100 non-null float64
memory usage: 2.0 KB
输出在某种程度上隐藏了节省的方式,但您可以查看内存使用量的值,以了解总节省量。
其中哪些在实践中效果更好取决于您的数据,所以您只需要尝试一下(或者甚至可以将它们组合起来)。