我有一个关于足球比赛结果的熊猫数据框。数据帧的每一行代表一场足球比赛。每场比赛的信息是:
Day | WinningTeamID | LosingTeamID | WinningPoints | LosingPoints | WinningFouls | ... |
1 13 1 45 5 3
1 12 4 21 12 4
即根据比赛结果来划分信息:输赢。 我想检索特定球队(例如 12 队)每场比赛的数据。
Day | Points | Fouls | ... |
1 21 4 ...
2 32 6 ...
最简单的方法是扫描整个数据框,检查特定的 teamID 是否在 WinningID 或 LosingID 上,然后基于此检索“Losing-columns”或“Winning-columns” 。 有没有更“优雅”的方式来切片 pandas 数据框? 这只会给我 12 队参与的比赛子集。
df[df[WinningTeamID == 12] | [LosingTeamID == 12]]
如何过滤这些数据并创建所需的数据框?
您基本上可以使用 where 子句来过滤数据框。
.query
选项允许您将条件传递到 Pandas 数据框。以下是针对您的具体问题的具体操作方法。
df.query['WinningTeamID == 12 | LosingTeamID == 12']
假设我们可以选择数据的格式。什么是理想的?因为我们 想要收集每个
TeamID
的统计数据,理想情况下我们会有一列 TeamID
以及每个统计数据的单独列,包括结果。
所以数据看起来像这样:
| Day | Outcome | TeamID | Points | Fouls |
| 1 | Winning | 13 | 45 | 3 |
| 1 | Losing | 1 | 5 | NaN |
| 1 | Winning | 12 | 21 | 4 |
| 1 | Losing | 4 | 12 | NaN |
以下是我们如何将给定的数据处理成所需的形式:
import numpy as np
import pandas as pd
df = pd.DataFrame({'Day': [1, 1], 'LosingPoints': [5, 12], 'LosingTeamID': [1, 4], 'WinningFouls': [3, 4], 'WinningPoints': [45, 21], 'WinningTeamID': [13, 12]})
df = df.set_index(['Day'])
columns = df.columns.to_series().str.extract(r'^(Losing|Winning)?(.*)', expand=True)
columns = pd.MultiIndex.from_arrays([columns[col] for col in columns],
names=['Outcome', None])
df.columns = columns
df = df.stack(level='Outcome').reset_index()
print(df)
产量
Day Outcome Fouls Points TeamID
0 1 Losing NaN 5 1
1 1 Winning 3.0 45 13
2 1 Losing NaN 12 4
3 1 Winning 4.0 21 12
现在我们可以使用
获取关于
TeamID
12的所有统计数据
print(df.loc[df['TeamID']==12])
# Day Outcome Fouls Points TeamID
# 3 1 Winning 4.0 21 12
df = df.set_index(['Day'])
将 Day
列移动到索引中。
将
Day
放入索引的目的是“保护”它免受操纵
(主要是 stack
调用)仅适用于标记为 Losing
或 Winning
的列。如果您有其他列,例如 Location
或
Officials
与 Day
一样,不属于 Losing
或 Winning
,那么
您也希望将它们包含在 set_index
调用中:例如df =
df.set_index(['Day', 'Location', 'Officials'])
。
尝试注释掉上面代码中的
df = df.set_index(['Day'])
。然后逐行执行代码。
特别是,比较 df.stack(level='Outcome')
在使用和不使用 set_index
调用时的样子:
与
df = df.set_index(['Day'])
:
In [26]: df.stack(level='Outcome')
Out[26]:
Fouls Points TeamID
Day Outcome
1 Losing NaN 5 1
Winning 3.0 45 13
Losing NaN 12 4
Winning 4.0 21 12
没有
df = df.set_index(['Day'])
:
In [29]: df.stack(level='Outcome')
Out[29]:
Day Fouls Points TeamID
Outcome
0 NaN 1.0 3.0 45 13
Losing NaN NaN 5 1
Winning 1.0 3.0 45 13
1 NaN 1.0 4.0 21 12
Losing NaN NaN 12 4
Winning 1.0 4.0 21 12
如果没有
set_index
调用,您最终会得到不需要的行 - Outcome
等于 NaN
的行。
目的
columns = df.columns.to_series().str.extract(r'^(Losing|Winning)?(.*)', expand=True)
columns = pd.MultiIndex.from_arrays([columns[col] for col in columns],
names=['Outcome', None])
就是创建一个多级列索引(称为 MultiIndex)其中 根据需要标记列
Losing
或 Winning
。
请注意,通过分离标签的 Losing
或 Winning
部分,
标签的其余部分变得重复。
我们最终得到一个数据框,
df
,例如,有两列标记为“点”。
这使得 Pandas 能够将这些列识别为某种程度上相似。
最大的收获——我们之所以不厌其烦地设置MultiIndex,是为了让这些“相似”的列可以通过调用
df.stack
来“统一”:
In [47]: df
Out[47]:
Outcome Losing Winning
Points TeamID Fouls Points TeamID
Day
1 5 1 3 45 13
1 12 4 4 21 12
In [48]: df.stack(level="Outcome")
Out[48]:
Fouls Points TeamID
Day Outcome
1 Losing NaN 5 1
Winning 3.0 45 13
Losing NaN 12 4
Winning 4.0 21 12
stack
、unstack
、set_index
和reset_index
是 4 个基本的 DataFrame 重塑操作。
df.stack
将列索引的一个或多个级别移动到行索引中。df.unstack
将行索引的一个或多个级别移动到列索引中。df.set_index
将列值移动到行索引中df.reset_index
将行索引的一个或多个级别移动到一列值中这 4 种方法一起允许您将 DataFrame 中的数据移动到您想要的任何位置 想要——在列中,行索引或列索引。
上面的代码是如何使用这些工具的示例(嗯,四个中的三个) 将数据重塑为所需的形式。
df.query('columnX == 15 | columnY == 25')