私はこのようなデータフレームを持っています
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
これらの行を取得するための最良の方法は何でしょうか?
ブールマスクによるフィルタリングを使用して、ソリューションを簡略化できます。
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)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加