我有一个看起来像这样的数据框
df = pd.DataFrame({'c1': ['a','a','a', 'b','b','a','a'],
'c2':[1,3,5,7,9,11,13],
'c3':[2,4,6,8,10,12,14]})
c1 c2 c3
0 a 1 2
1 a 3 4
2 a 5 6
3 b 7 8
4 b 9 10
5 a 11 12
6 a 13 14
每次列c1中的值更改时,我都希望获得第一行和最后一行。
在此示例中,输出为
c1 c2 c3
0 a 1 2
2 a 5 6
3 b 7 8
4 b 9 10
5 a 11 12
6 a 13 14
我可以使用
idx = np.where(df.c1.ne(df.c1.shift()) != 0)[0]
获得像这样的第一行
df.iloc[idx,:]
c1 c2 c3
0 a 1 2
3 b 7 8
5 a 11 12
但无法获取最后一行
c1 c2 c3
2 a 5 6
4 b 9 10
6 a 13 14
获取这些行的最佳方法是什么?
答案 0 :(得分:1)
您可以通过布尔掩码过滤来简化解决方案:
df1 = df[df.c1.ne(df.c1.shift())]
print (df1)
c1 c2 c3
0 a 1 2
3 b 7 8
5 a 11 12
df2 = df[df.c1.ne(df.c1.shift(-1))]
print (df2)
c1 c2 c3
2 a 5 6
4 b 9 10
6 a 13 14
对于|
,bitwise OR
的所有行链条件:
df3 = df[df.c1.ne(df.c1.shift()) | df.c1.ne(df.c1.shift(-1))]
print (df3)
c1 c2 c3
0 a 1 2
2 a 5 6
3 b 7 8
4 b 9 10
5 a 11 12
6 a 13 14
性能:
显然不是groupby解决方案更快,但是对真实数据的最佳测试是
#7k rows
df = pd.concat([df] * 1000, ignore_index=True)
In [53]: %timeit df.groupby(df.c1.ne(df.c1.shift()).cumsum(), as_index=False).nth([0, -1])
3.57 ms ± 283 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [54]: %timeit df[df.c1.ne(df.c1.shift()) | df.c1.ne(df.c1.shift(-1))]
1.53 ms ± 6.79 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
答案 1 :(得分:0)
您不需要两项操作,groupby
+ nth
使您可以在单个步骤中获得第一行和最后一行。
df.groupby(df.c1.ne(df.c1.shift()).cumsum(), as_index=False).nth([0, -1])
c1 c2 c3
0 a 1 2
2 a 5 6
3 b 7 8
4 b 9 10
5 a 11 12
6 a 13 14