最近在用pandas做一个机器学习的项目,训练集大概2G。我用的dataFrame来操作数据,对训练集做了一次groupby和mean的操作,速度还挺快的,但把得到的结果赋值给用户参数(也是一个dataframe表)的时候,速度缺特别慢,请问这是什么原因呢?
训练集大概有7000多万行,做groupby和mean操作大概十几分钟也就完成了,但赋值操作缺超级慢,每秒钟大概只能赋值50条左右,差距太大了。其中赋值语句大概是这样操作的:
dataframeA.loc[user,'']=dataframeB.loc[user,'']。两张dataFrame表都很大,都是百万级的,不知道是不是和量级较大有关,但千万级的训练集做groupby也没什么压力啊,而且这个机器学习项目,会经常使用和修改表中的参数,如果都这么慢的话,可能就无法正常使用了,哪位大神有什么好的解释或者建议吗?非常感谢了。部分代码如下,有什么细节没有说清楚的话可以问我,我再详细解释下。
def get_average_rating(self):
self.u = log_train['Result'].mean()
print 'u is ',self.u
i,j = 0,0
user_mean_rate = log_train.groupby('UserId').agg({'Result':np.mean})
item_mean_rate = log_train.groupby('ItemId').agg({'Result':np.mean})
#计算bias
print 'calc bias start'
start_time = time.time()
for user in train_users:
i += 1
if i%2000==0:
print '2000 used time',time.time()-start_time
start_time = time.time()
self.user_params.loc[user,'bias'] = user_mean_rate.loc[user,'Result']-self.u
for item in train_items:
self.item_params.loc[item,'bias'] = item_mean_rate.loc[item,'Result']-self.u
print 'bias total used time',time.time()-start_time
Pandas dispose d'un générateur de df.iterrows() pour parcourir les lignes de DataFrame, ce qui est le plus efficace.
Pour plus de détails, veuillez consulter la documentation :
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.iterrows.html
Je n'ai jamais rien fait de cette ampleur, mais mon expérience est qu'il est préférable de ne pas opérer df un par un, c'est fondamentalement lent et l'ensemble du fonctionnement de la colonne est beaucoup plus rapide
Ajouter. (ajouter)
Il est préférable d'écrire toutes les nouvelles valeurs dans un df vide, puis de fusionner
, mais parfois il est inévitable d'ajouter directement
2 Il est plus rapide de supprimer
. et utilisez directement l'instruction del
3 . Changer
adopte également l'idée de fusionner, en écrasant la valeur d'origine
Je ne pense pas que l'affectation soit lente
self.user_params.loc[user,'bias'] équivaut à prendre l'index de deuxième niveau de l'index de premier niveau, ce qui devrait être très lent
Pouvez-vous mettre l'élément et l'utilisateur. Que diriez-vous de le diviser en deux trames de données ?
loc est le plus lent. Essayez d'utiliser ix à la place. Il est préférable d'utiliser des iterrows pour construire une boucle.