python 连续比较_【Python效率】五种Pandas循环方法效率对比

本专栏招募作者及编辑,感兴趣分享学习R/Python数据分析/机器学习知识的可以私信联系

PS:有人提到一个问题很好,如果每次循环都采用比较复杂的操作似乎用向量化很难实现,我的建议是尽可能拆分成向量化操作,如果不行建议用numpy硬写然后用numba包加速。

正文:

如果你使用过Python及Pandas,那么你很有可能已经使用了for循环去进行某些数据分析操作。不幸的是,绝大部分Python新手使用的下标循环语句实际上是非常之慢的,即便在小数据集上也会消耗大量的运行时间。本专栏之前的一些文章已经涉及了这方面的讨论,在这篇文章中文兄进一步特意对五种不同的For Loop方法进行横向对比,使大家更加明晰自己平时写的各种For循环到底效率几何。

注意:之后代码里出现的df是一个只有一个column叫做test的dataframe。另外各方法下面的代码均只是用法举例,并不和测试速度用的代码完全一致。测试代码原文如下:https://towardsdatascience.com/how-to-make-your-pandas-loop-71-803-times-faster-805030df4f06​towardsdatascience.com

方法1:下标循环(速度等级: )

df1 = df

for i in range(len(df)):

if df.iloc[i]['test'] != 1:

df1.iloc[i]['test'] = 0

下标循环是通过循环一个下标数列,通过iloc去不断get数据,这个方法是新手最常用的但也是最慢的,在测试例子中大概需要21.9s。

方法2:Iterrows循环 (速度等级: )

i = 0

for ind, row in df.iterrows():

if row['test'] != 1:

df1.iloc[i]['test'] = 0

i += 1

该循环方式是通过iterrows进行循环,ind和row分别代表了每一行的index和内容。测试例子大概需要0.07s,比起下标循环速度提升了321倍。

方法3:Apply循环(速度等级: )

df1['test'] = df['test'].apply(lambda x: x if x == 1 else 0)

Apply是pandas的一个常用函数,通常的用法是内接一个lambda匿名函数,从而对dataframe的每一行都进行循环处理。在测试例子中,apply的速度为0.027s,比下标循环快了811倍。

方法4:Pandas内置向量化函数(速度等级: )

res = df.sum()

Pandas为我们提供了大量的内置向量化函数,比如sum,mean就可以快速计算某一列的求和和平均。在测试例子中速度为0.00236s,比下标循环快了9280倍。

方法5:Numpy向量化函数(速度等级: )

df_values = df.values

res = np.sum(df_values)

最后一种方法是将Pandas的数据转化为Numpy的Array,然后使用Numpy的内置函数进行向量化操作。在测试例子中速度为0.000305s,比下标循环快了71800倍。

下面是详细的速度对比图,来自之前链接:

Sources:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Python实现连续变量最优分箱详解,我可以为您提供一些基础的思路和代码实现。该方法是基于CART算法实现的,具体如下: 首先,我们需要导入相关的库,包括numpy、pandas和sklearn等: ```python import numpy as np import pandas as pd from sklearn.tree import DecisionTreeRegressor ``` 然后,我们需要定义一个函数来执行最优分箱操作,该函数的输入参数包括待分箱的数据、目标变量、最小样本数、最大分箱数、以及是否需要返回分箱结果等: ```python def binning_continuous_var(data, target, min_samples_leaf=50, max_bins=10, return_bins=False): # 将数据和目标变量拼接 data = pd.concat([data, target], axis=1) # 获取连续变量的列名 cont_cols = data.select_dtypes(include=[np.number]).columns.tolist() # 循环处理每个连续变量 for col in cont_cols: # 对该变量进行分箱操作 binned_col, bins = bin_continuous_var(data, col, target, min_samples_leaf, max_bins) # 将分箱结果更新到数据集中 data[col] = binned_col # 如果需要返回分箱结果,则返回数据集和分箱边界 if return_bins: return data, bins # 否则,仅返回数据集 else: return data ``` 接下来,我们需要定义一个子函数来执行单个连续变量的分箱操作,该函数的输入参数包括待分箱的数据、连续变量的列名、目标变量、最小样本数和最大分箱数等: ```python def bin_continuous_var(data, col, target, min_samples_leaf, max_bins): # 获取该变量的取范围 data_range = data[col].max() - data[col].min() # 如果取范围为0,则直接返回原始变量和一个空的分箱边界列表 if data_range == 0: return data[col], [] # 否则,使用CART算法进行分箱操作 else: # 初始化决策树模型 tree_model = DecisionTreeRegressor( criterion='mse', min_samples_leaf=min_samples_leaf, max_leaf_nodes=max_bins, random_state=42 ) # 拟合决策树模型 tree_model.fit(data[col].to_frame(), target) # 获取决策树的叶节点数目 n_leaves = tree_model.get_n_leaves() # 如果叶节点数目大于等于最大分箱数,则需要重新设置最大叶节点数目并重新拟合模型 while n_leaves >= max_bins: max_bins -= 1 tree_model = DecisionTreeRegressor( criterion='mse', min_samples_leaf=min_samples_leaf, max_leaf_nodes=max_bins, random_state=42 ) tree_model.fit(data[col].to_frame(), target) n_leaves = tree_model.get_n_leaves() # 获取叶节点的取范围 leaves_range = [(tree_model.tree_.threshold[i - 1], tree_model.tree_.threshold[i]) for i in np.where(tree_model.tree_.children_left == -1)[0]] # 初始化分箱边界列表,将最小和最大作为边界的起点和终点 bins = [data[col].min()] + [i[1] for i in leaves_range[:-1]] + [data[col].max()] # 计算每个取所对应的分箱编号 binned_col = np.digitize(data[col], bins) # 将分箱编号转换为分箱中心点的取 binned_col = pd.Series(binned_col, index=data.index) binned_col = binned_col.map(lambda x: np.round(np.mean(data[target.name][binned_col == x]), 4)) # 返回分箱结果和分箱边界列表 return binned_col, bins ``` 最后,我们可以使用上述代码实现对连续变量的最优分箱操作,例如: ```python # 生成测试数据 data = pd.DataFrame({ 'col1': np.random.rand(1000), 'col2': np.random.rand(1000), 'col3': np.random.rand(1000), 'target': np.random.randint(0, 2, 1000) }) # 执行最优分箱操作 data_binned = binning_continuous_var(data.drop('target', axis=1), data['target'], min_samples_leaf=50, max_bins=10, return_bins=False) ``` 以上就是Python实现连续变量最优分箱的基础思路和代码实现,希望可以对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值