【问题标题】:How to use Pandas to do a conditional VLOOKUP using two columns as an index for the VLOOKUP?如何使用 Pandas 使用两列作为 VLOOKUP 的索引来执行条件 VLOOKUP?
【发布时间】:2020-07-13 01:57:01
【问题描述】:

我对 Pandas 和 Python 还很陌生,我根本不知道如何做一些在 Excel 中很容易完成的事情。我希望能从社区中得到一点帮助。

假设我有以下内容,这是一个与梦幻足球相关的 df,它具有三列 - “名称”、“年份”和“FantasyPts”。代码如下。

import pandas as pd

df = pd.DataFrame({'Name': ['Tom Brady', 'Tom Brady', 'Tom Brady', 'Patrick Mahomes', 'Patrick Mahomes', 'Patrick Mahomes'],
                   'Year': [2019, 2018, 2017, 2019, 2018, 2017],
                   'FantasyPts': [300, 350, 400, 500, 400, 50],
                   })

我想在名为“FantasyPtsPreviousYear”的表中添加另一列,但在 Pandas / Python 中如何做到这一点非常困难。

我想做的是:

  1. 对于表中的每一行,让 python/pandas 检查 df 的该行中的名称和年份。
  2. 查看同一玩家在上一年(即第 1 年)获得的幻想积分
  3. 将该数字填充到名为“FantasyPtsPreviousYear”的 df 新行中,或者,如果没有该玩家上一年的数据,则输入 0。

在 Excel 中,我只需创建新列并将这些列与 VLOOKUP 一起使用。我在 Pandas 中找到的与 VLOOKUP 最接近的东西是合并,但这似乎在这里不起作用(或者至少我不知道如何使它与这个特定的应用程序一起工作)。在尝试找到答案后,我认为它可能与 loc() 函数和 For 循环有关,但我无法让它工作。

感谢您提供的任何帮助!我非常感谢它,并认为这个社区提供的所有帮助都很棒!

【问题讨论】:

    标签: python pandas dataframe vlookup


    【解决方案1】:

    让我们试试groupbyshift

    df = df.sort_values(['Name','Year'],ascending=[True,True])
    df['FantasyPtsPreviousYear'] = df['FantasyPts'].groupby(df['Name']).shift().fillna(0)
    

    【讨论】:

    • 我建议将其调整为 df['FantasyPts'].groupby(df['Name']).shift(periods=1, fill_value=0)
    • 非常感谢!还要感谢 Ben 的建议!我能够在我的数据集上很好地工作。唯一的问题是下面提到的@ALollz。我意识到这不在我的原始示例 df 中,但是如果我在我的数据集中添加了另一行,如下所示: df = df.append({'Name': 'Tom Brady', 'Year': 2011, 'FantasyPts ': 450}, ignore_index=True),然后 Tom Brady 2017 'FantasyPtsPreviousYear' 列返回为 450(Brady 2011 年的统计数据)而不是 0 或 NaN。有没有办法来解决这个问题?无论哪种方式,非常感谢您非常有帮助和及时的回复。非常感谢!
    【解决方案2】:

    我相信这可以通过where()shift() 的组合来实现。但是,这需要预先对数据进行排序。这是给定您提供的数据的代码:

    df = df.sort_values(['Name','Year'],ascending=[True,True])
    df['FantasyPtsPreviousYear'] = df['FantasyPts'].shift().where(df['Name'].eq(df['Name'].shift())).fillna(0)
    print(df)
    

    这个输出:

                  Name  Year  FantasyPts  FantasyPtsPreviousYear
    5  Patrick Mahomes  2017          50                     0.0
    4  Patrick Mahomes  2018         400                    50.0
    3  Patrick Mahomes  2019         500                   400.0
    2        Tom Brady  2017         400                     0.0
    1        Tom Brady  2018         350                   400.0
    0        Tom Brady  2019         300                   350.0
    

    【讨论】:

    • 非常感谢您的快速而有帮助的回复!我能够在我的数据集上很好地工作。唯一的问题是下面提到的@ALollz。我意识到这不在我的原始示例 df 中,但如果我在我的数据集中添加了另一行,如下所示: df = df.append({'Name': 'Tom Brady', 'Year': 2011, 'FantasyPts ': 450}, ignore_index=True),然后 Tom Brady 2017 'FantasyPtsPreviousYear' 列返回为 450(Brady 2011 年的统计数据)而不是 0 或 NaN。有没有办法来解决这个问题?无论哪种方式,非常感谢您非常有帮助和及时的回复。非常感谢!
    • 感谢您也回复我的回答,我建议您使用 ALollz 方法,因为它可以更好地解决丢失年份的问题,但是这种简单的解决方案可能更容易,它有更多限制,因为它适用于从头到尾的所有年份都在数据框中并正确排序。
    【解决方案3】:

    merge 带有自身的 DataFrame,您在其中将 1 添加到年份。这为每个玩家明确定义了 Year -> Year-1 的比赛

    (注意shift,除非您确定您每年都有一行。如果不明确重新索引所有年份,组内的shift 将为您提供您拥有的最后一年数据,无论是 1 年前还是 10 年前(如果缺少数据))


    df = df.merge((df.assign(Year=df['Year']+1)
                     .rename(columns={'FantasyPts': 'FantasyPts_prev'})), 
                  how='left', on=['Name', 'Year'])
    df['FantasyPts_prev'] = df['FantasyPts_prev'].fillna(0, downcast='infer')
    
                  Name  Year  FantasyPts  FantasyPts_prev
    0        Tom Brady  2019         300              350
    1        Tom Brady  2018         350              400
    2        Tom Brady  2017         400                0
    3  Patrick Mahomes  2019         500              400
    4  Patrick Mahomes  2018         400               50
    5  Patrick Mahomes  2017          50                0
    

    【讨论】:

    • 非常感谢!我什至没有意识到您标记的问题(当我每年没有一行时使用 shift)并且非常感谢您标记它,因此它不会让我因每年没有行的不同数据集而绊倒我。阅读您的评论后,我在 df 中添加了另一行,如下所示: df = df.append({'Name': 'Tom Brady', 'Year': 2011, 'FantasyPts': 450}, ignore_index=True) 并实现您的解决方案仍然有效,而 shift 似乎提供了您上面提到的错误。非常感谢您的回复!非常有帮助!
    • 我可以编辑/建议在末尾添加fillna(0) 以完全匹配 OP 的输出吗?我还要感谢您指出使用 shift 的问题,考虑到它非常重要,因为它可能会破坏整个分析!
    • @CeliusStingher 是的,以后可以随意编辑。无论如何它都会通知我,如果我不同意,我可以在编辑中解决它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多