pandas - 根据第一次出现的情况删除行

时间:2016-06-24 13:47:26

标签: python pandas

以下是较大字典的示例

 data ={'StudentId':['AAdams','AAdams','AAdams','AAdams','AAdams','AAdams',
                'BBrooks','BBrooks','BBrooks','BBrooks','BBrooks',],

'year':[2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016],
'month':[11,11,11,11,12,12,12,12,12,1,1],
'day':[15,16,21,23,1,2,15,18,30,5,7],
'BookLevel':[1.5,1.5,1.2,1.4,1.7,1.8,3.2,3.1,3.8,3.3,3.4]}

我想从每个学生的第一个月开始删除第一次出现的最大值。如果有第二次出现,我想保留该事件

我通过StudentId,年和月使用groupby并计算了最大值  BookLevel。

然后我做了另一个数据框来计算每个学生每月的最大值并合并了两个数据框

然后我有一个如下所示的数据框:

       StudentId year   month   BookLevel   BookLevelMax
    0   AAdams  2015    11      1.5         1.5
    1   AAdams  2015    11      1.5         1.5
    2   AAdams  2015    11      1.2         1.5
    3   AAdams  2015    11      1.4         1.5
    4   AAdams  2015    12      1.7         1.8
    5   AAdams  2015    12      1.8         1.8
    6   BBrooks 2015    12      3.2         3.8
    7   BBrooks 2015    12      3.1         3.8
    8   BBrooks 2015    12      3.8         3.8
    9   BBrooks 2016    1       3.3         3.4
   10   BBrooks 2016    1       3.4         3.4

我希望在第12个月第一次出现1.5的AAdams和第3次出现在第12个月的BBrooks

我可以使用df.drop删除BookLevel Max等于BookLevel的行...但是它会为每个学生每月删除最大值并删除 第一次出现和第二次出现,如果有两次。

       StudentId    year    month   BookLevel   BookLevelMax
  2     AAdams      2015    11        1.2        1.5
  3     AAdams      2015    11        1.4        1.5
  4     AAdams      2015    12        1.7        1.8
  6     BBrooks     2015    12        3.2        3.8
  7     BBrooks     2015    12        3.1        3.8
  9     BBrooks     2016    1         3.3        3.4

我似乎无法找到一种只删除第一次出现的方法,而且只能在第一个月出现。具体来说AAdams在第11个月最多只有1.5个。它有两次发生。我想保留其中一行但是放弃其他行......我想在AAdams下保持1.8行,因为它发生在第二个月(其他学生在第一个月之后的几个月内发生)。希望这是有道理的。

2 个答案:

答案 0 :(得分:0)

试试这个

# sort and reindex
df = df.sort('col').reset_index()

#slice to first occurrence of your value
df.loc[: df[(df['col'] == 'row')].index[0], :]

答案 1 :(得分:0)

原始问题(如上所述):

下面是一个更大的字典的样本,它变成了dfdata

data ={'StudentId':['AAdams','AAdams','AAdams','AAdams','AAdams','AAdams',
            'BBrooks','BBrooks','BBrooks','BBrooks','BBrooks',],

'year':[2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016],
'month':[11,11,11,11,12,12,12,12,12,1,1],
'day':[15,16,21,23,1,2,15,18,30,5,7],
'BookLevel':[1.5,1.5,1.2,1.4,1.7,1.8,3.2,3.1,3.8,3.3,3.4]}

我想从每个学生的第一个月开始删除第一次出现的最大值。如果有第二次出现,我想保留这种情况。除了每个学生的第一个月,我不想改变任何月份

这是我的新解决方案:

 df =dfdata.sort_values(by=['StudentId','year','month','BookLevel'],ascending = [True,True,True,False]) 

这使得第一个月的最高BookLevel成为每组StudentID,年,月的顶部。

然后我使用cumcount做了一个groupby。这使得第一个月每个学生的每个最高级别水平旁边都为零。

 df1 = (df.groupby('StudentId').cumcount())

然后我通过选择没有零的所有行来做一个组

df2 = df(df.groupby('StudentId').cumcount() !=0])

任务完成! 原创尝试是一个很好的例子,可以看到渐进式进展但却忽略了原来的目标。