У меня есть датафрейм с четырьмя столбцами: имя, учетная запись, дата и баллы
Мне нужно сгруппировать по имени и учетной записи, а затем заполнить пропущенные даты баллами за предыдущие дни.
Я знаю, как это сделать, но я не знаю, как это сделать быстро. Мой фактический кадр данных - это миллионы и миллионы строк.
Вот упрощенная версия проблемы. Я хочу получить тот же вывод, но сделать это намного, намного быстрее при заполнении большого количества данных.
(фактические данные поступают из файлов Excel.)
import pandas as pd
data = """
name account date points
Steve e12 2014-02-07 17
Steve e12 2014-02-09 18
Steve g52 2014-02-03 52
Steve g52 2014-02-06 25
Steve g52 2014-02-08 31
Steve g52 2014-02-09 40
Fred g21 2014-02-02 17
Fred g21 2014-02-08 19
Fred g52 2014-02-07 21
Fred g52 2014-02-09 18
"""
dates = pd.date_range("2014-02-01", "2014-02-10")
def fill_in_dates(part_df):
part_df.index = pd.DatetimeIndex(part_df.date)
part_df = part_df.reindex(dates)
part_df = part_df.fillna(method='ffill')
return part_df
lines = [line.strip().split() for line in data.splitlines()[2:] if line.strip()]
columns = data.splitlines()[1].split()
df = pd.DataFrame(lines, columns=columns)
df = df.groupby(['name', 'account'], as_index=False).apply(fill_in_dates)
df = df.dropna()
df = df.reset_index()
df.date = df.level_1
df = df.drop(['level_0', 'level_1'], axis=1)
print(df)
А вот и вывод:
name account date points
0 Fred g21 2014-02-02 17
1 Fred g21 2014-02-03 17
2 Fred g21 2014-02-04 17
3 Fred g21 2014-02-05 17
4 Fred g21 2014-02-06 17
5 Fred g21 2014-02-07 17
6 Fred g21 2014-02-08 19
7 Fred g21 2014-02-09 19
8 Fred g21 2014-02-10 19
9 Fred g52 2014-02-07 21
10 Fred g52 2014-02-08 21
11 Fred g52 2014-02-09 18
12 Fred g52 2014-02-10 18
13 Steve e12 2014-02-07 17
14 Steve e12 2014-02-08 17
15 Steve e12 2014-02-09 18
16 Steve e12 2014-02-10 18
17 Steve g52 2014-02-03 52
18 Steve g52 2014-02-04 52
19 Steve g52 2014-02-05 52
20 Steve g52 2014-02-06 25
21 Steve g52 2014-02-07 25
22 Steve g52 2014-02-08 31
23 Steve g52 2014-02-09 40
24 Steve g52 2014-02-10 40