【问题标题】:Conditional filtering of pandas data frame熊猫数据框的条件过滤
【发布时间】:2017-11-20 08:07:13
【问题描述】:

我有一个关于足球结果的 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 是否在 WinningID 或 LosingID 上,然后在此基础上检索“失败的列”或“获胜的列”。 有没有更“优雅”的方式来切片熊猫数据框? 这只会给我包含 12 队参与的比赛的子集。

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

如何过滤这些数据并创建所需的数据框?

【问题讨论】:

    标签: python pandas filter slice


    【解决方案1】:
    df.query['WinningTeamID == 12 | LosingTeamID == 12']
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    • pandas 数据框中的 .query 选项可以更轻松地传递 SQL 查询,例如选择数据
    【解决方案2】:

    假设我们可以选择数据的格式。什么是理想的?因为我们 想要收集每个TeamID 的统计信息,理想情况下我们会有一个TeamIDs 列 并为每个统计数据(包括结果)单独列。

    所以数据看起来像这样:

    | 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])
    

    是创建一个多级列索引(称为a MultiIndex) 其中 标签列Losing 或Winning 视情况而定。 请注意,通过分离标签的Losing 或Winning 部分, 标签的其余部分将重复。

    我们最终得到一个 DataFrame,df,例如,有两列标记为“Points”。 这允许 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 中的数据移动到您想要的任何位置 want -- 在列、行索引或列索引中。

    上面的代码是如何使用这些工具的示例(好吧,四个中的三个) 将reshape data 转换为所需的形式。

    【讨论】:

    • 谢谢!这绝对可以完成工作!我对 pandas 很陌生,你能解释一下为什么你在“Day”使用 set_index 吗?下一行的目的是什么?我理解的唯一部分是您提取包含 Losing 或 Winning 的列。
    【解决方案3】:

    我觉得应该更像:

    df.query('columnX == 15 | columnY == 25')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 2019-04-13
      • 2015-05-28
      • 2018-02-06
      • 2018-09-28
      相关资源
      最近更新 更多