如何仅保留熊猫数据帧每组的前n%行?

时间:2018-11-17 22:35:37

标签: python pandas pandas-groupby

我看到了这个问题的一个变体,要求将每个组的前n行保留在pandas数据框中,而解决方案在这里Pandas get topmost n records within each group使用n作为绝对数字而不是百分比。但是,在我的数据框中,每个组中都有不同数量的行,我想保留每个组中前n%个行。我将如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

groupby之前,您可以构造一系列布尔标志和过滤器。首先,让我们创建一个示例数据框,并查看第一个系列中每个唯一值的行数:

np.random.seed(0)
df = pd.DataFrame(np.random.randint(0, 2, (10, 3)))

print(df[0].value_counts())

0    6
1    4
Name: 0, dtype: int64

然后定义一个分数,例如低于50%,并构造一个布尔级数进行过滤:

n = 0.5

g = df.groupby(0)
flags = (g.cumcount() + 1) <= g[1].transform('size') * n

然后应用条件,将索引设置为第一个序列,并(如果需要)对索引进行排序:

df = df.loc[flags].set_index(0).sort_index()

print(df)

   1  2
0      
0  1  1
0  1  1
0  1  0
1  1  1
1  1  0

如您所见,结果数据帧仅具有3个0索引和2个1索引,在每种情况下均为原始数据帧中数字的一半。

答案 1 :(得分:1)

这是您提到的帖子中某些答案的另一种选择

首先,这里是一个快速功能,可以向上或向下取整。如果我们希望数据框的前30%的行长8行,那么我们将尝试使用2.4行。因此,我们将需要向上或向下取整。

我的首选是四舍五入。这是因为,对于eaxample,如果我们要占据50%的行,但是只有一组只有一行,那么我们仍然会保留那一行。我将其分开放置,以便您可以根据需要更改舍入

def round_func(x, up=True):
    '''Function to round up or round down a float'''
    if up:
        return int(x+1)
    else:
        return int(x)

接下来,我制作一个要使用的数据框,并将参数p设置为每个组中应保留的行的分数。一切都遵循了,我已经对其进行了评论,希望您可以遵循。

import pandas as pd
df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})

p = 0.30 # top fraction to keep. Currently set to 80%
df_top = df.groupby('id').apply(                        # group by the ids
    lambda x: x.reset_index()['value'].nlargest(        # in each group take the top rows by column 'value'
        round_func(x.count().max()*p)))        # calculate how many to keep from each group

df_top = df_top.reset_index().drop('level_1', axis=1)   # make the dataframe nice again

df看起来像这样

   id  value
0   1      1
1   1      2
2   1      3
3   2      1
4   2      2
5   2      3
6   2      4
7   3      1
8   4      1

df_top看起来像这样

   id  value
0   1      3
1   2      4
2   2      3
3   3      1
4   4      1