事实证明这比看起来更复杂。肯定有办法简化我找到的解决方案,但我会逐步解决这个问题,因此很明显发生了什么。
但首先值得花一点时间来问为什么这很棘手。看起来很简单 groupby() 问题,使用 .cumsum() 加起来的输赢。如果你只想获得访问团队的结果,那就是。但你的问题是你希望获得胜利 团队,期间 ,无论他们是在访问还是在家。
groupby()
.cumsum()
要做到这一点,我建议将问题分解为几个步骤(当你遇到一些有问题的代码时,总是有用的事情)。
的 主要答案 强>
首先,将您的数据分成两个数据帧,一个用于访问团队,另一个用于主队:
vdf = nba.set_index(['Season', 'Date', 'Visitor']) vdf['win'] = np.where(vdf['H_PTS'] < vdf['V_PTS'], 1, 0) vdf.index.names = ['Season', 'Date', 'Team'] hdf = nba.set_index(['Season', 'Date', 'Home']) hdf['win'] = np.where(hdf['H_PTS'] > hdf['V_PTS'], 1, 0) hdf.index.names = ['Season', 'Date', 'Team']
一旦拆分,我们就会对每个数据帧做两件事。首先,我们正在创建一个 win 列使用 np.where() (完全是pythonic,顺便说一下。我会说只是使用布尔值,但这并不能很好地发挥作用 .cumsum() )。其次,我们重命名索引,而不是访问者和主队,我们只是谈论团队。这很重要,因为现在我们要将这些数据框合并为一个:
win
np.where()
df = pd.concat([vdf, hdf]) df['loss'] = 1 - df.win df = df.sort_index(level=['Date']) gr = df.groupby(level=['Season', 'Team'])
我们可以算一个 loss 对于一个团队来说,作为一个简单的反向 win 秒。然后我们按照排序 Date - 由于没有球队可以同时打两场比赛,这应该没问题。然后我们将分组 Season 和 Team ,因为那是你想要计算结果的组。
loss
Date
Season
Team
现在累计输入和输出总结非常简单:
df['wins'] = gr.win.apply(lambda g: g.shift().cumsum().fillna(0)) df['losses'] = gr.loss.apply(lambda g: g.shift().cumsum().fillna(0))
如果你想获得包括当前游戏在内的结果,你可以使用 .cumsum() 。但是因为你想要在之前的游戏中得到结果,我们需要使用 .shift() ,然后用0填充(现在为空)第一行。
.shift()
但现在我们遇到了一个问题:家庭和访客团队在不同的行!为了解决这个问题,我们再次将它们拆分为单独的数据帧并重命名列,以明确我们是否在谈论访问者或家庭记录。
vdf = df.dropna(subset=['Home'])[['wins', 'losses']].rename(columns=lambda c: 'V_' + c) hdf = df.dropna(subset=['Visitor'])[['wins', 'losses']].rename(columns=lambda c: 'H_' + c)
最后一个真正的步骤是合并回基于的主数据帧 Visitor 和 Home 球队名称。
Visitor
Home
nba = nba.merge(vdf.astype(int), left_on=['Season', 'Date', 'Visitor'], right_index=True) nba = nba.merge(hdf.astype(int), left_on=['Season', 'Date', 'Home'], right_index=True)
最后,我们可以(可选)生成那种 W-L 你在评论中提到的格式:
W-L
nba['V_winloss'] = nba['V_wins'].astype(str) + '-' + nba['V_losses'].astype(str) nba['H_winloss'] = nba['H_wins'].astype(str) + '-' + nba['H_losses'].astype(str)
完成!进一步简化它(绝对可以完成)留给读者练习。
的 所有代码都在一个地方: 强>
vdf = nba.set_index(['Season', 'Date', 'Visitor']) vdf['win'] = np.where(vdf['H_PTS'] < vdf['V_PTS'], 1, 0) vdf.index.names = ['Season', 'Date', 'Team'] hdf = nba.set_index(['Season', 'Date', 'Home']) hdf['win'] = np.where(hdf['H_PTS'] > hdf['V_PTS'], 1, 0) hdf.index.names = ['Season', 'Date', 'Team'] df = pd.concat([vdf, hdf]) df['loss'] = 1 - df.win df['location'] = np.where(pd.notnull(df['Home']), 'h', 'v') df = df.sort_index(level=['Date']) gr = df.groupby(level=['Season', 'Team']) df['wins'] = gr.win.apply(lambda g: g.shift().cumsum().fillna(0)) df['losses'] = gr.loss.apply(lambda g: g.shift().cumsum().fillna(0)) vdf = df.dropna(subset=['Home'])[['wins', 'losses']].rename(columns=lambda c: 'V_' + c) hdf = df.dropna(subset=['Visitor'])[['wins', 'losses']].rename(columns=lambda c: 'H_' + c) nba = nba.merge(vdf.astype(int), left_on=['Season', 'Date', 'Visitor'], right_index=True) nba = nba.merge(hdf.astype(int), left_on=['Season', 'Date', 'Home'], right_index=True) nba['V_winloss'] = nba['V_wins'].astype(str) + '-' + nba['V_losses'].astype(str) nba['H_winloss'] = nba['H_wins'].astype(str) + '-' + nba['H_losses'].astype(str)
的 一个例子(以及一些建议) 强>
每当您有问题时,请尝试构建所需输入和所需输出的样本,格式化为答案者可以将其直接复制粘贴到代码中。此示例应演示您的任务的关键要求。在你的情况下,这可能包括一个既能打主场比赛又能打多场比赛的球队。在您提出问题之前,这是一项非常有用的练习 - 使用基本案例构建测试台可以轻松检查您编写的代码是否按预期工作。
我已经制作了包含这些功能的示例数据框。请注意,我删除了与手头问题无关的列。
>>> nba Season Date Visitor Home V_PTS H_PTS 0 1 1 A E 1 2 1 1 2 B E 1 0 2 1 3 C E 1 2 3 1 4 D E 1 0 4 1 5 E A 1 2 5 1 6 E B 1 0 6 1 7 E C 1 2 7 1 8 E D 1 0 8 2 9 A E 1 2
在计算了输赢之后( df['losses'] = ... ),您应该检查团队结果是否正确累积:
df['losses'] = ...
>>> print df[['wins', 'losses']].sort_index(level=['Team', 'Date']).astype(int) wins losses Season Date Team 1 1 A 0 0 5 A 0 1 2 9 A 0 0 1 2 B 0 0 6 B 1 0 3 C 0 0 7 C 0 1 4 D 0 0 8 D 1 0 1 E 0 0 2 E 1 0 3 E 1 1 4 E 2 1 5 E 2 2 6 E 2 3 7 E 3 3 8 E 3 4 2 9 E 0 0
然后到最后,你会得到这个:
Season Date Visitor Home V_PTS H_PTS V_wins V_losses H_wins \ 0 1 1 A E 1 2 0 0 0 1 1 2 B E 1 0 0 0 1 2 1 3 C E 1 2 0 0 1 3 1 4 D E 1 0 0 0 2 4 1 5 E A 1 2 2 2 0 5 1 6 E B 1 0 2 3 1 6 1 7 E C 1 2 3 3 0 7 1 8 E D 1 0 3 4 1 8 2 9 A E 1 2 0 0 0 H_losses V_winloss H_winloss 0 0 0-0 0-0 1 0 0-0 1-0 2 1 0-0 1-1 3 1 0-0 2-1 4 1 2-2 0-1 5 0 2-3 1-0 6 1 3-3 0-1 7 0 3-4 1-0 8 0 0-0 0-0
您可以查看它以确保它符合您的要求。