pandas数据帧过滤行像groupby

时间:2017-01-04 14:01:06

标签: performance pandas numpy dataframe

例如,我有dataframe这两列ab

a = [1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3]
b = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]

我期待过滤的数据框:[5,6,7,2,3,4,9,0,1]

不使用groupby函数(因为使用非常大的dataframe花费太长时间,它只是不可用),如何使用col中每个组的最后3个项目进行过滤。 a

2 个答案:

答案 0 :(得分:2)

您可以先drop_duplicates使用groups的最后一行,然后获取以前的索引值,最后按loc选择:

a = [1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3]
b = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]
df =  pd.DataFrame({'a': a, 'b':b})
print (df)
    a  b
0   1  1
1   1  2
2   1  3
3   1  4
4   1  5
5   1  6
6   1  7
7   2  8
8   2  9
9   2  0
10  2  1
11  2  2
12  2  3
13  2  4
14  3  5
15  3  6
16  3  7
17  3  8
18  3  9
19  3  0
20  3  1
df1 = df.drop_duplicates('a',keep='last')
print (df1)
    a  b
6   1  7
13  2  4
20  3  1

idx = sorted(df1.index.tolist() + (df1.index - 1).tolist() + (df1.index - 2).tolist())
print (idx)
[4, 5, 6, 11, 12, 13, 18, 19, 20]

print (df.loc[idx])
    a  b
4   1  5
5   1  6
6   1  7
11  2  2
12  2  3
13  2  4
18  3  9
19  3  0
20  3  1

答案 1 :(得分:2)

方法#1:以下是基于NumPy的方法 -

In [89]: a = np.array([1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3])
    ...: b = np.array([1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1])
    ...: 

In [90]: idx = np.append(np.nonzero(a[1:] > a[:-1])[0], a.size-1)[:,None] - [2,1,0]

In [91]: b[idx].ravel()
Out[91]: array([5, 6, 7, 2, 3, 4, 9, 0, 1])

如果您从数据框的列中分别收到df ab的列作为预处理步骤,我们需要将它们作为数组提取,例如所以 -

a = df.a.values
b = df.b.values

请注意,这假定每组至少有三个元素。对于每组小于3元的情况,请继续阅读下一个方法。

方法#2:使用Scipy's binary dilation创建一个掩码,用于选择b以外的元素 -

from scipy.ndimage.morphology import binary_dilation as imdilate
def filter_lastN(a, b, N):
    mask = np.zeros(a.size,dtype=bool)
    mask[np.append(np.nonzero(a[1:] > a[:-1])[0],b.size-1)] = 1
    return b[imdilate(mask,np.ones(N),origin=(N-1)//2)]

示例运行 -

In [198]: a
Out[198]: array([1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3])

In [199]: b
Out[199]: array([5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1])

In [200]: filter_lastN(a,b,3)
Out[200]: array([5, 6, 7, 2, 3, 4, 9, 0, 1])

In [201]: filter_lastN(a,b,5)
Out[201]: array([5, 6, 7, 0, 1, 2, 3, 4, 7, 8, 9, 0, 1])