Pandas数据框的条件过滤

3

我可以帮您翻译关于IT技术的中文内容,以下是需要翻译的内容:

我有一个有关足球比赛结果的Pandas数据框架。数据框架的每一行代表一场足球比赛。每场比赛的信息包括:

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是否在WinningIDLosingID上,然后基于此检索"Losing-columns"或"Winning-columns"。 是否有更加"优雅"的方法来切片pandas数据帧? 这将简单地给出涉及12号队的比赛子集。

df[df[WinningTeamID == 12] | [LosingTeamID == 12]]

我该如何过滤这些数据并创建所需的数据框?
3个回答

6
df.query['WinningTeamID == 12 | LosingTeamID == 12']

虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - undefined
在pandas dataframe中,.query选项使得像传递SQL查询一样选择数据更加容易。 - undefined

2
假设我们可以选择数据格式。什么样的格式最理想?由于我们想要按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 放入索引的目的是为了“保护”它免受旨在仅针对标记为LosingWinning的列(主要是stack调用)的操纵。如果您有其他列,例如像 Day 一样与LosingWinning无关的LocationOfficials等,则也需要在 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

Without 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),将“输掉”的或“赢得”的标签分别标记为LosingWinning。通过将标签的“输掉”或“赢得”部分分离出来,可以使标签的剩余部分重复。最终获得一个名为df的DataFrame,例如有两列标签为“Points”,这使得Pandas能够将这些列识别为相似的列。

通过设置多级索引,我们可以通过调用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

stackunstackset_indexreset_index 是四个基本的 DataFrame 重塑操作。

  • df.stack 将列索引的一个或多个级别移动到行索引中。
  • df.unstack 将行索引的一个或多个级别移动到列索引中。
  • df.set_index 将列值移动到行索引中。
  • df.reset_index 将行索引的一个或多个级别移动到值的列中。

这四种方法可以让您将数据从 DataFrame 中的任何位置移动到所需的位置,包括列、行索引或列索引。

上面的代码是如何使用这些工具(实际上是其中三个)来重塑数据为所需形式的示例。


谢谢!这绝对能胜任!我对pandas还比较新,你能解释一下为什么在'Day'上使用set_index吗?接下来的那行代码的目的是什么?唯一我明白的部分是你提取了包含“Losing”或“Winning”的列。 - undefined

1
我认为应该更像这样:
df.query('columnX == 15 | columnY == 25')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接