質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

12043閲覧

Python 列の上下の値を比較し、同じならば上の行を削除、を繰り返して実行するやり方

shu_magi

総合スコア19

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/12/03 04:54

編集2018/12/03 04:58

前提・実現したいこと

初心者です。初めて投稿するため、記載に不足があったら教えていただけると助かります。
以下のエラー回避方法、または他のデータ処理方法があれば教えていただきたいです。

csvファイルのなかで、
上下の列の値を比較し、
値が同じならば上の行を削除
というプログラムを書きたいと考えています。

以下を参考にプログラムを作成しました。
pandas.DataFrameの任意の位置のデータを選択し処理
https://note.nkmk.me/python-pandas-at-iat-loc-iloc/

特定の行を削除する
https://pythondatascience.plavox.info/pandas/%E8%A1%8C%E3%83%BB%E5%88%97%E3%82%92%E5%89%8A%E9%99%A4

データ例(テストデータでは、500行分のデータを使用しています)
data_id floor
0 1 6
1 2 8
2 3 9
3 4 3
4 5 2
5 6 6
6 7 6
7 8 3
8 9 8
9 10 4
10 11 6
11 12 0
12 13 0
13 14 5
14 15 9
15 16 7
16 17 5
17 18 3
18 19 9
19 20 7
20 21 -1
21 22 7
22 23 8
23 24 0
24 25 2
25 26 4
26 27 1
27 28 3
28 29 8
29 30 7
.. ... ...

以下のコードで処理を実行しようとしました。

Python

1import pandas as pd 2 3#データ読み込み 4filename="data_test.csv" 5df = pd.read_csv(filename, engine='python') 6 7for i in range(len(df)): 8 if df.iat[i,1] == df.iat[i-1,1]: 9 print(df.iat[i,0], df.iat[i,1]) 10 df.drop(i-1,inplace=True)

発生している問題・エラーメッセージ

以下エラーが発生します。
データフレームの長さをrangeに入れているのに対して、処理実行により処理後のデータフレームの長さが短くなっているからか?と考えていますが回避方法がわからないため、質問させていただきました。

--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-22-2d387042cd5b> in <module>() 8 9 for i in range(len(df)): ---> 10 if df.iat[i,1] == df.iat[i-1,1]: 11 print(df.iat[i,0], df.iat[i,1]) 12 df.drop(i-1,inplace=True) ~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py in __getitem__(self, key) 2140 2141 key = self._convert_key(key) -> 2142 return self.obj._get_value(*key, takeable=self._takeable) 2143 2144 def __setitem__(self, key, value): ~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py in _get_value(self, index, col, takeable) 2531 if takeable: 2532 series = self._iget_item_cache(col) -> 2533 return com._maybe_box_datetimelike(series._values[index]) 2534 2535 series = self._get_item_cache(col) IndexError: index 463 is out of bounds for axis 0 with size 463

補足情報

他の列削除方法がもしあれば教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

問題点は

(1) df.iat[i,1]df.iat[i-1,1] を比較しているのであれば、iの範囲は 0 ~ len(df)-1ではなく 1 ~ len(df)-1なのでは?

(2) ループは 上に書いたように 1 ~ len(df)-1 の範囲で回るが、ループ内の処理にてdfの行が削除されるため、 iの範囲の整合が取れなくなっている

ということで、直すとすると行の削除処理をループの外で行うように修正して

Python

1import pandas as pd 2#データ読み込み 3filename="data_test.csv" 4df = pd.read_csv(filename, engine='python') 5 6del_list = [] 7for i in range(1,len(df)): 8 if df.iat[i,1] == df.iat[i-1,1]: 9 print(df.iat[i,0], df.iat[i,1]) 10 del_list.append(i-1) 11df.drop(del_list,inplace=True)

となるかと思います。
が・・

この手の処理をおこなうのであればループ処理を行うのではなく shift()を使って

Python

1df = df.loc[df.iloc[:,1] != df.shift(-1).iloc[:,1]]

のように書いたほうが良いのではないでしょうか

投稿2018/12/03 06:02

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shu_magi

2018/12/04 09:09

magichanさん ありがとうございます!どちらのコードでも処理できました! コード1行で処理できるのですね、驚きでした。 後学のため、なぜこのコードで処理できているのか教えていただけると大変助かります。 ・shift(-1)で上の行削除をしている認識
magichan

2018/12/04 10:33

まず、shift() は文字通り行をシフトさせるメソッドです。今回は引数に -1 を設定しておりますので、これによりDataFrame全体が上側に1つシフトします。 で、もとの DataFrame と 1つ上側にシフトさせたDataFrame の2列目(floor)を df.iloc[:,1] != df.shift(-1).iloc[:,1] のように比較することにより、下の行と値が違う箇所が True、同じ箇所に Falseとなった Booleanのリストが得られますので、このリストでDataFrameを df.loc[df.iloc[:,1] != df.shift(-1).iloc[:,1]] とフィルタリングすることで True の箇所(下の行と値が違う箇所)のみを得ることができます。
shu_magi

2018/12/05 08:44

magichanさん 詳細な説明ありがとうございました!助かりました!
guest

0

indexオーバーなのでこれで動くはず

Python

1import pandas as pd 2 3#データ読み込み 4filename="data_test.csv" 5df = pd.read_csv(filename, engine='python') 6 7for i in range(len(df)-1): 8 if df.iat[i,1] == df.iat[i-1,1]: 9 print(df.iat[i,0], df.iat[i,1]) 10 df.drop(i-1,inplace=True)

投稿2018/12/03 05:07

yamato_user

総合スコア2321

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shu_magi

2018/12/03 05:49

回答ありがとうございます。 頂いたものを試したのですが変わらず以下エラーが出てしまいました。。 ndexError Traceback (most recent call last) <ipython-input-23-657ac0a6c153> in <module>() 8 9 for i in range(len(df)-1): ---> 10 if df.iat[i,1] == df.iat[i-1,1]: 11 print(df.iat[i,0], df.iat[i,1]) 12 df.drop(i-1,inplace=True) ~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexing.py in __getitem__(self, key) 2140 2141 key = self._convert_key(key) -> 2142 return self.obj._get_value(*key, takeable=self._takeable) 2143 2144 def __setitem__(self, key, value): ~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py in _get_value(self, index, col, takeable) 2531 if takeable: 2532 series = self._iget_item_cache(col) -> 2533 return com._maybe_box_datetimelike(series._values[index]) 2534 2535 series = self._get_item_cache(col) IndexError: index 463 is out of bounds for axis 0 with size 463
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問