根据列中的值获取数据帧组的第一行和最后一行

时间:2019-02-11 06:32:32

标签: python pandas

我有一个看起来像这样的数据框

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

获取这些行的最佳方法是什么?

2 个答案:

答案 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