Python 按日期填写Pandas中的行,条件是行不存在

Python 按日期填写Pandas中的行,条件是行不存在,python,pandas,Python,Pandas,如果下一个日期不存在前一行,那么如何从按日期索引的Pandas数据框中“复制”前一行。这是由以下问题引起的 问题 我的例子是数据 DATE | TEAM | PLAYER -----+------+------- 0 | A | John 0 | A | Tom 0 | B | Chris 0 | B | Rob 1 | A | John 1 | A | George 1 | B | Chris

如果下一个日期不存在前一行,那么如何从按日期索引的Pandas数据框中“复制”前一行。这是由以下问题引起的

问题

我的例子是
数据

DATE | TEAM | PLAYER
-----+------+-------
 0   |  A   |  John
 0   |  A   |  Tom
 0   |  B   |  Chris
 0   |  B   |  Rob
 1   |  A   |  John
 1   |  A   |  George
 1   |  B   |  Chris
 2   |  A   |  Rob
我试图在object
X
的基础上进行构建,这样我就可以像

X.loc[date, team]
它将返回所有
球员
,他们的最后一次观察是在
日期为
团队

现在说清楚,我想

X.loc[0, 'A'] = ['John', 'Tom']
X.loc[0, 'B'] = ['Chris', 'Rob']

X.loc[1, 'A'] = ['John', 'Tom', 'George']
X.loc[1, 'B'] = ['Chris', 'Rob']

X.loc[2, 'A'] = ['John', 'Tom', 'George', 'Rob']
X.loc[2, 'B'] = ['Chris']
创意

我的想法是,我可以为在该日期未被观察到的玩家“填入”以前日期的值,例如,
data\u filled

DATE | TEAM | PLAYER | FILLED
-----+------+--------+-------
 0   |  A   |  John  |   0
 0   |  A   |  Tom   |   0
 0   |  B   |  Chris |   0
 0   |  B   |  Rob   |   0
 1   |  A   |  John  |   0
 1   |  A   |  George|   0
 1   |  B   |  Chris |   0
 1   |  A   |  Tom   |   1
 1   |  B   |  Rob   |   1
 2   |  A   |  Rob   |   0
 2   |  A   |  John  |   1
 2   |  A   |  George|   1
 2   |  B   |  Chris |   1
 2   |  A   |  Tom   |   1
其中,我添加了一个
填充的
列,以表示该行是否已添加到
数据
。现在,我相信我能得到我想要的

X = data_filled.set_index(['DATE', 'TEAM'])
我可以用它

X.loc[data, team]
获取玩家名单

返回最后一次观察日期为团队的所有球员

您可以定义一个自定义的
loc
函数,而不是构造一个数据帧来使用
dataframe.loc

给定日期
n
,我们可以使用以下方法获得所有球员的最后一支球队:

last_team = df[df.DATE<=n].groupby('PLAYER').TEAM.agg('last')
根据需要在函数调用中组合上述两个步骤

def myloc(frame, date, team):
    last_team = frame[frame['DATE']<=date].groupby('PLAYER')['TEAM'].agg('last')
    return last_team.index[last_team == team].values
一种更高性能的方法是使用pd.merge_asof构建给定日期的球员及其最新团队成员表

首先,我们必须建立一个所有可能的球员和日期表

df2 = pd.DataFrame(index=pd.MultiIndex.from_product([df.DATE.unique(), df.PLAYER.unique()])).reset_index()
df2.columns = ['DATE', 'PLAYER']
df3 = pd.merge_asof(df2, df, on='DATE', by='PLAYER').set_index(['DATE', 'TEAM']).sort_index()

df3
# outputs
           PLAYER
DATE TEAM
0    A       John
     A        Tom
     B      Chris
     B        Rob
     NaN   George
1    A       John
     A        Tom
     A     George
     B      Chris
     B        Rob
2    A       John
     A        Tom
     A        Rob
     A     George
     B      Chris
然后,您可以使用
loc
获取上次被观察到为一支球队踢球的球员

df3.loc[0, 'A'].PLAYER.values
# outputs: array(['John', 'Tom'], dtype=object)

这种向前的方式将每个球员最后一次知道的球队填入未来的日期。我创建了中间变量,以避免出现一个庞大的单行程序

ffilled = df.set_index(['PLAYER', 'DATE']).unstack().ffill(axis=1)
tidy = ffilled.stack().reset_index()
result = tidy.set_index(['DATE', 'TEAM']).sort_index()

result
               PLAYER
DATE TEAM        
0    A       John
     A        Tom
     B      Chris
     B        Rob
1    A     George
     A       John
     A        Tom
     B      Chris
     B        Rob
2    A     George
     A       John
     A        Rob
     A        Tom
     B      Chris

result.loc[1, 'A']
           PLAYER
DATE TEAM        
1    A     George
     A       John
     A        Tom

result.loc[1, 'A'].values.flatten().tolist()
['George', 'John', 'Tom']

这对我来说毫无意义:
X.loc[1,'B']=['Chris','Rob'];X.loc[1,'B']=['Chris']
。你到底要不要Rob?这是一个输入错误,最后两个应该是日期2。我不确定我是否可以在电话上编辑,但回到电脑前会编辑。克里斯和罗布不应该在[2,B]吗?不,问题是,罗布将转到A队,因为这是我们最后一次看到他效力的球队。我喜欢这样,我想知道使用它与构建新的数据帧有什么性能差异。这肯定比构建数据帧1并只查找值要差。您的数据框架可能会有多大?
df3.loc[0, 'A'].PLAYER.values
# outputs: array(['John', 'Tom'], dtype=object)
ffilled = df.set_index(['PLAYER', 'DATE']).unstack().ffill(axis=1)
tidy = ffilled.stack().reset_index()
result = tidy.set_index(['DATE', 'TEAM']).sort_index()

result
               PLAYER
DATE TEAM        
0    A       John
     A        Tom
     B      Chris
     B        Rob
1    A     George
     A       John
     A        Tom
     B      Chris
     B        Rob
2    A     George
     A       John
     A        Rob
     A        Tom
     B      Chris

result.loc[1, 'A']
           PLAYER
DATE TEAM        
1    A     George
     A       John
     A        Tom

result.loc[1, 'A'].values.flatten().tolist()
['George', 'John', 'Tom']