我怎样才能加快填写Pandas的日期?

2024-06-16 10:01:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含四列的数据框:name、account、date和points

我需要按姓名和帐户分组,然后用前几天的点数填写缺少的日期。你知道吗

我知道怎么做,但我不知道怎么做得快。我的实际数据帧是数百万行。你知道吗

下面是这个问题的简化版本。我想得到相同的输出,但是在填充大量数据时,要使其更快。你知道吗

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

Tags: 数据namedfdatadateaccountfredpoints
3条回答

我认为您唯一的选择是在日期范围内调用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

我认为不为每个组执行part_df.index = pd.DatetimeIndex(part_df.date),而是在整个数据帧级别执行,可以节省一些时间。然后只对“points”列执行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的长度

用途:

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

相关问题 更多 >