Заполнение недостающих данных историческим средним быстро и эффективно в пандах - PullRequest
1 голос
/ 20 октября 2019

Я работаю с большим набором панельных данных (продольные данные) с 500 тыс. Наблюдений. В настоящее время я пытаюсь заполнить недостающие данные (не более 30% наблюдений), используя среднее значение до момента времени t каждой переменной. (Причина, по которой я не заполняю данные общим средним значением, состоит в том, чтобы избежать предвзятого отношения, связанного с использованием данных, доступных только в более поздний момент времени.)

Я написал следующую функцию, которая выполняетзадание, но выполняется очень медленно (5 часов для строк по 500 тыс. !!). В общем, я считаю, что заполнение недостающих данных в Pandas - трудоемкая задача в вычислительном отношении. Пожалуйста, расскажите мне, как вы обычно заполняете пропущенные значения, и как вы заставляете его работать быстро

Функция для заполнения средним значением до времени "t":

def meanTillTimeT(x,cols):
    start = time.time()
    print('Started')
    x.reset_index(inplace=True)
    for i in cols:
        l1 =[]
        for j in range(x.shape[0]):
            if x.loc[j,i] !=0 and np.isnan(x.loc[j,i]) == False :
                l1.append(x.loc[j,i])
            elif np.isnan(x.loc[j,i])==True :
                x.loc[j,i]=np.mean(l1)      
    end = time.time()
    print("time elapsed:", end - start)
    return x

1 Ответ

0 голосов
/ 20 октября 2019

Давайте построим DataFrame для иллюстрации:

import pandas as pd
import numpy as np

df = pd.DataFrame({"value1": [1, 2, 1, 5, np.nan, np.nan, 8, 3],
                   "value2": [0, 8, 1, np.nan, np.nan, 8, 9, np.nan]})

Вот DataFrame:

      value1  value2
   0     1.0     0.0
   1     2.0     8.0
   2     1.0     1.0
   3     5.0     NaN
   4     NaN     NaN
   5     NaN     8.0
   6     8.0     9.0
   7     3.0     NaN

Теперь я предлагаю сначала вычислить кумулятивные суммы, используя панд. DataFrame.cumsum , а также количество значений, отличных от NaN, для вычисления средних значений. После этого достаточно заполнить NaN этими средствами и вставить их в исходный DataFrame. Оба действия используют pandas.DataFrame.fillna , что будет намного быстрее, чем циклы Python:

df_mean = df.cumsum() / (~df.isna()).cumsum()
df_mean = df_mean.fillna(method = "ffill")
df = df.fillna(value = df_mean)

Результат:

      value1  value2
   0    1.00     0.0
   1    2.00     8.0
   2    1.00     1.0
   3    5.00     3.0
   4    2.25     3.0
   5    2.25     8.0
   6    8.00     9.0
   7    3.00     5.2
...