将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()
在这里,我重命名得分列,以便当我将其加入到原始数据帧时,我知道哪个列是哪个。这可能没有必要,但我不确定。
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.
提前致谢!!!
答案 0 :(得分: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)中完成,但恕我直言,简单性大大超过通常较小的性能损失。