pythonで重複するデータをキレイにする方法です。
株の場合、権利日が年の途中で変更になったりすると、同じ年のレコードが2件存在します。
今回は、重複データの抽出と処理方法のご紹介です。
pandasの重複処理
重複データを削除するのか、別の処理をするのかなど、対応方法は色々あります。
重複で先に登場したものを残す場合
# 重複した行を抽出する(処理しないのは、最初の行なら、firstで指定) duplicated = df[df.duplicated(subset=['code','year'], keep='first')]
重複で後に登場したものを残す場合
# 重複した行を抽出する(処理しないのは、最初の行なら、firstで指定) duplicated = df[df.duplicated(subset=['code','year'], keep='last')]
重複データ両方の確認
#''でくくらない duplicated = df[df.duplicated(subset=['code','year'], keep=False)]
重複データのindexを取得したい場合
# 重複する行のインデックスを取得 duplicated_list = duplicated.index.to_list() # 重複する行の他のカラムを指定する場合 duplicated_list = duplicated['code'].to_list()
#重複データのindexを文字列にする
#文字列に変換 StrA = ','.join([str(_) for _ in duplicated_list])
重複indexを文字列にすると次のような検索が可能
#重複したデータのみを抽出 df.query('index in [' + StrA +']') #中身は、duplicatedと一緒
pandasで2つの列を指定条件にして、データを抽出する方法
import pandas as pd # データを作成する data = {'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50], 'C': [100, 200, 300, 400, 500]} df = pd.DataFrame(data) # A列が2より大きく、B列が40より小さい場合のC列の値を取得する result = df.loc[(df['A'] > 2) & (df['B'] < 40), 'C'] # 結果を表示する print(result)
上記の例では、loc
メソッドを使用して、'A' > 2
かつ'B' < 40
という条件を指定して、’C’列の値を取得しています。&
演算子を使用して2つの条件を組み合わせています。必要に応じて、他の演算子(|
、~
)を使用して条件を組み合わせることができます。また、’C’列だけでなく、必要な列を取得することができます。
抽出条件をif文に取り入れる場合
if not result.empty: # resultにデータが含まれる場合の処理 else: # resultが空の場合の処理
この例では、result.empty
属性を使用して、result
が空の場合を判定しています。empty
属性は、DataFrameやSeriesオブジェクトが空の場合にTrueを返します。
もしくは、条件式を使用してTrueかFalseを直接取得することもできます。以下は、条件を満たす行がある場合にTrueを返す例です。
直接書いてもOK!
if not df.loc[(df['A'] > 2) & (df['B'] < 40)].empty: # 条件を満たす行がある場合の処理 else: # 条件を満たす行がない場合の処理
シンプルに見やすく記述するなら
condition_1 = df['A'] > 2 condition_2 = df['B'] < 40 result = df.loc[condition_1 & condition_2, 'C']
‘A’列が配列データである場合、条件式にはisin
関数を使用して、複数の値を比較することができます。以下は例です。
# 'A'列の値が[2, 3, 5]のいずれかであり、'B'列の値が40以下の行を抽出する場合 conditions = (df['A'].isin([2, 3, 5])) & (df['B'] <= 40) result = df.loc[conditions, 'C']
このように、isin
関数を使用することで、配列データを含む’A’列の条件式を簡単に書くことができます。
もし’A’列にNaNが含まれている場合には、
notna
関数を使用して、NaNを含まない行のみを処理することもできます。以下は例です。# 'A'列の値が[2, 3, 5]のいずれかであり、NaNを含まない行で、'B'列の値が40以下の行を抽出する場合 conditions = (df['A'].isin([2, 3, 5])) & (df['A'].notna()) & (df['B'] <= 40) result = df.loc[conditions, 'C']
重複データをベースに処理をしたいなら
冒頭で、抽出した重複リストを利用する場合
conditions = (df['A'].isin([duplicated_list])) & (df['A'].notna()) & (df['B'] <= 40) result = df.loc[conditions, 'C']