如何加快填写熊猫的日期?

时间:2018-11-08 21:13:27

标签: python pandas dataframe pandas-groupby

我有一个包含四列的数据框:名称,帐户,日期和点数

我需要按名称和帐户分组,然后用前几天的点数填写缺失的日期。

我知道该怎么做,但我不知道该怎么迅速做。我的实际数据帧是数以百万计的行。

这是问题的简化版本。我希望获得相同的输出,但是在填充大量数据时要使它快得多。

(实际数据来自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

3 个答案:

答案 0 :(得分:1)

我认为您唯一的选择是在日期范围内拨打groupbyreindex

def reindex(g):
    return g.reindex(pd.date_range(g.index.min(), g.index.max()))

df['date'] = pd.to_datetime(df['date'], errors='coerce')
(df.set_index('date')
   .groupby(['name', 'account'])
   .points.apply(reindex)
   .ffill()
   .rename_axis(['name', 'account', 'date'])
   .reset_index())

     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     g52 2014-02-07     21
8    Fred     g52 2014-02-08     21
9    Fred     g52 2014-02-09     18
10  Steve     e12 2014-02-07     17
11  Steve     e12 2014-02-08     17
12  Steve     e12 2014-02-09     18
13  Steve     g52 2014-02-03     52
14  Steve     g52 2014-02-04     52
15  Steve     g52 2014-02-05     52
16  Steve     g52 2014-02-06     25
17  Steve     g52 2014-02-07     25
18  Steve     g52 2014-02-08     31
19  Steve     g52 2014-02-09     40

答案 1 :(得分:0)

我认为您可以通过不为每个组执行part_df.index = pd.DatetimeIndex(part_df.date)而是在整个数据帧级别上节省一些时间。然后,仅在“点”列上执行groupby,并同时执行多个操作,而不是重新分配df。整个操作如下:

df = pd.DataFrame(lines, columns=columns)
df = (df.set_index(pd.to_datetime(df.date))
        .groupby(['name', 'account'])['points'].apply(lambda x: x.reindex(dates).ffill())
        .dropna().reset_index().rename(columns={'level_2':'date'}))

,您将得到相同的结果。不确定大型数据集的改进幅度是多少,但是在示例中您给出的改进速度约为2.4倍。这可能取决于您拥有的组数和dates

的长度

答案 2 :(得分:0)

使用:

df.set_index('date')\
  .groupby(['name','account'], as_index=False, group_keys=False)\
  .apply(lambda x: x.reindex(pd.date_range(x.index.min(), 
                                           x.index.max(), freq='D'))
                    .ffill())\
  .reset_index()

输出:

        index   name account points
0  2014-02-02   Fred     g21     17
1  2014-02-03   Fred     g21     17
2  2014-02-04   Fred     g21     17
3  2014-02-05   Fred     g21     17
4  2014-02-06   Fred     g21     17
5  2014-02-07   Fred     g21     17
6  2014-02-08   Fred     g21     19
7  2014-02-07   Fred     g52     21
8  2014-02-08   Fred     g52     21
9  2014-02-09   Fred     g52     18
10 2014-02-07  Steve     e12     17
11 2014-02-08  Steve     e12     17
12 2014-02-09  Steve     e12     18
13 2014-02-03  Steve     g52     52
14 2014-02-04  Steve     g52     52
15 2014-02-05  Steve     g52     52
16 2014-02-06  Steve     g52     25
17 2014-02-07  Steve     g52     25
18 2014-02-08  Steve     g52     31
19 2014-02-09  Steve     g52     40