【问题标题】:Python pandas: Identify Records Based on Multiple Criteria on Multiple FieldsPython pandas:基于多个字段上的多个条件识别记录
【发布时间】:2015-01-08 23:06:04
【问题描述】:

将 IPython (Python 3.4) 与 pandas 一起使用:我有一个大致如下所示的数据框(注意每个学生的重复记录,有时每个学生有 3 个以上的记录):

Year    Subject   Student   Score   Date
2014    Math       1        34     31-Jan
2014    Math       1        34     26-Jan
2014    Math       2        65     26-Jan
2014    Math       2        76     31-Jan
2014    Math       3        45     3-Feb
2014    Math       3        67     31-Jan

我正在寻找一种方法来根据以下标准返回每个学生的分数: 1.最高分 当每个学生记录的分数相同时: 2. 最近日期

这是所需的输出:

Year    Subject   Student   Score   Date
2014    Math       1        34     31-Jan
2014    Math       2        76     31-Jan
2014    Math       3        67     31-Jan

这是我迄今为止尝试过的: 在年份、学科和学生上使用 groupby 以获得给定年份和学科领域每个学生的最高分:

by_duplicate = df.groupby(['Year', 'Subject', 'Student'])
HighScore = by_duplicate[['Year', 'Subject', 'Student', 'Score']].max()

在这里,我重命名了 score 列,以便当我将它加入到原始数据框时,我知道哪一列是哪一列。这可能没有必要,但我不确定。

HighScore.rename(columns={'Score': 'Score2'}, inplace=True)

在这里,我添加了一个空白的“HighScore”列,以期如果该行具有最高分,稍后将填充 1。稍后会详细介绍...

HighScore['HighScore'] = ""

然后我对最近的日期做同样的事情:

Recent = by_duplicate[['Year', 'Subject', 'Student', 'Date']].max()
Recent.rename(columns={'Date': 'Date2'}, inplace=True)
Recent['Recent'] = ""

My approach was to 
1. create tables for each field (score and date) using groupby, 
2. identify the rows containing the highest and most recent scores, respectively, by entering a "1" in their respective new columns (HighScore' and 'Recent')
3. somehow join these grouped tables back to the original dataframe on Year, Subject, and Student
-I'm guessing this requires somehow ungrouping the groups as the pd.merge is not working on the grouped data frames
4. The end result, according to my theory, would look something like this:

Year    Subject   Student   Score   Date     HighScore  Recent
2014    Math       1        34     31-Jan    1          1   
2014    Math       1        34     26-Jan    1          0
2014    Math       2        65     26-Jan    0          0  
2014    Math       2        76     31-Jan    1          1  
2014    Math       3        45     3-Feb     0          1  
2014    Math       3        67     31-Jan    1          0

And once I have this table, I would need to do something like this:
1. Per student for a given year and subject area: return the sum of 'HighScore'
2. If the sum of 'HighScore' is greater than 1, then take the 'Recent' row equal to 1.
I believe this will give me what I need.

提前致谢!!!

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    如果我的理解正确,我认为您可以通过对分数和日期进行排序来简化此操作,以便每个组的最后一个元素始终是最高分中的最新元素。我可能会做类似的事情

    >>> df["FullDate"] = pd.to_datetime(df["Year"].astype(str) + "-" + df["Date"], 
                         format="%Y-%d-%b")
    >>> df = df.sort(["Score", "FullDate"])
    >>> df.groupby(["Year", "Subject", "Student"]).tail(1)
       Year Subject  Student  Score    Date   FullDate
    0  2014    Math        1     34  31-Jan 2014-01-31
    5  2014    Math        3     67  31-Jan 2014-01-31
    3  2014    Math        2     76  31-Jan 2014-01-31
    

    首先我创建了一个FullDate 列,它是一个真正的日期时间而不是一个字符串,所以我知道它会正确排序。

    请注意,我们排序的顺序很重要:我们首先要按分数,然后在最大分数内最后是“最大”(最近)日期。相反,如果我们用另一种方式来做,我们就会有

    >>> df = df.sort(["FullDate", "Score"]) # THIS IS THE WRONG ORDER
    >>> df.groupby(["Year", "Subject", "Student"]).tail(1)
       Year Subject  Student  Score    Date   FullDate
    0  2014    Math        1     34  31-Jan 2014-01-31
    3  2014    Math        2     76  31-Jan 2014-01-31
    4  2014    Math        3     45   3-Feb 2014-02-03
    

    这将为我们提供最近一天的最高分。

    现在排序确实是 ~O(N log N),找到最大值可以在 O(N) 内完成,但恕我直言,简单性大大超过了通常较小的性能损失。

    【讨论】:

    • 天才!我不确定 ~O(N log N) 和 O(N) 是什么意思,但非常感谢!一个后续问题:当我尝试将这些记录附加到现有表时,使用 groupby 的事实是否会造成问题?
    猜你喜欢
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    相关资源
    最近更新 更多