如何加速这个Python功能?

时间:2018-03-12 23:12:28

标签: python pandas

我希望可以提出这类问题。

我有一个get_lags函数,它接受一个数据框,对于每一列,将列移动到列表n_lags中的每个n。因此,如果n_lags = [1, 2],该函数将每列一次移动一次,一次移动两个位置,以这种方式创建新的滞后列。

def get_lags (df, n_lags):
    data =df.copy()
    data_with_lags = pd.DataFrame()
    for column in data.columns:
        for i in range(n_lags[0], n_lags[-1]+1):
            new_column_name = str(column) + '_Lag' + str(i)
            data_with_lags[new_column_name] = data[column].shift(-i) 
    data_with_lags.fillna(method = 'ffill', limit = max(n_lags), inplace = True)
    return data_with_lags

所以,如果:

df.columns
ColumnA
ColumnB

然后,get_lags(df, [1 , 2]).columns将是:

ColumnA_Lag1
ColumnA_Lag2
ColumnB_Lag1
ColumnB_Lag2

问题:使用包含大约100,000行和20,000列的数据框,这需要永远运行。在一台16 GB的RAM,核心i7 windows机器上,一旦我等了15分钟才能运行代码,然后才停止它。无论如何我可以调整这个功能,使其更快?

2 个答案:

答案 0 :(得分:1)

这可能不适用于您的情况(我希望我理解您正在尝试正确执行的操作),但您可以通过不首先执行此操作来大幅加速。您可以将列视为ring buffer吗?

不要在事后更改列,而是跟踪:

  • 您可以使用多少列(每个条目有多少个滞后项)
  • 使用的最后一个滞后列是什么
  • (可选)您旋转了多少次"

所以不要移动数据,而是执行以下操作:

current_column = (current_column + 1) % total_columns

然后写下该栏目。

答案 1 :(得分:1)

您需要shift + concat。这是简洁版 -

def get_lags(df, n_lags):
    return pd.concat(
       [df] + [df.shift(i).add_suffix('_Lag{}'.format(i)) for i in n_lags],
       axis=1
    )

这是一个更友好的内存版本,使用for循环 -

def get_lags(df, n_lags):
    df_list = [df]
    for i in n_lags:
        v = df.shift(i)
        v.columns = v.columns + '_Lag{}'.format(i)    
        df_list.append(v)

    return pd.concat(df_list, axis=1)