首页 > 解决方案 > 寻找运行速度更快的代码或运行时间是否合理的意见

问题描述

这是在 Python 中

我正在尝试用 x 替换数据框中的 NaN 值,x ~ N.trunc(upper, lower, mu, sigma)
数据框的形状约为 (150000,150)

import scipy.stats as stats

df = pd.read_csv(r'C:\Users\User\Desktop\Coding\Data Project\df1.csv')

for k in df.columns:
    upper  = np.nanmax(df[str(k)])
    lower  = np.nanmin(df[str(k)])
    mu     = df.loc[:,str(k)].mean()
    sigma  = df.loc[:,str(k)].std()
    def fill_nan(column_value): #fill_nan finds NaN values and replaces them with x, N.trunc(upper, lower, mu, sigma,)
        if np.isnan(column_value) == True: 
            column_value = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma).rvs()
        return column_value
    df[str(k)] = df[str(k)].apply(fill_nan) # runs fill_nan on each column
print('NaN count on dataframe is :%d' %df.isnull().sum().sum())
df.to_csv(r'C:\Users\User\Desktop\Coding\Data Project\df2.csv')
#run-time about 7 minutes

请估计 7 分钟的运行时间是否适合完成此任务,以及如果可能的话,我如何加速此代码或编写其他更快的代码。

谢谢你。

标签: pythonpandasiterationapply

解决方案


有很多东西需要优化:

1. 仅将列转换为字符串一次

您有很多行包含str(k). 将您的代码转换为仅将密钥转换为字符串一次,方法是k=str(k)在开始时执行一次,然后将所有其他事件替换为k

2.fill_nan只声明一次函数

基本上和以前一样,把函数的声明移出循环。

3.优化fill_nan功能numba

看看https://numba.pydata.org

4. 完全不要使用自己fill_nan

df.fillna您可以简单地使用该方法,而不是遍历每列中的每个单元格。这样您就不需要应用前面的 2 个步骤

您没有提供示例 csv,因此以下代码未经测试:

for k in df.columns:
    k = str(k)
    upper  = np.nanmax(df[k])
    lower  = np.nanmin(df[k])
    mu     = df.loc[:,k].mean()
    sigma  = df.loc[:,k].std()

    column_value = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma).rvs()
    df[k] = df[k].fillna(column_value)

5. 完全不要循环

这比代码性能更具有可读性,但您也应该能够做到:

您没有提供示例 csv,因此以下代码未经测试:

upper  = np.nanmax(df)
lower  = np.nanmin(df)
mu     = df.mean()
sigma  = df.std()

norm_values = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma).rvs()
df = df.fillna(pd.Series(norm_values))

推荐阅读