こんにちは。
最近はPythonにも触れてる僕です。
今は社内の業務効率化で、経理がExcelとCsvを使って手作業で行っている入金消込処理をPythonを使って自動化を試みています。
※「未だにExcelなの?」のようなツッコミはご遠慮ください。
当初はVBAかC#を使うかと思いましたが、せっかくならデータ処理が得意との噂のPythonを使ってみようと思い、はじめてPythonに触れてみてます。
Excel操作にopenpyxl、データ処理にpandasを使っているのですが、未だにpandasには手を焼いており、**C#**なら瞬殺でコードが組める処理でも苦戦したりしています。
そんな苦戦したことをメモ代わりに書き残していきます。
今回のメモはこちら。
##Pandas.DataFrameで複数の条件を満たす行を削除する方法
「そんなん簡単じゃん!」とツッコミが入るかもですが、いろいろ試してたのでメモっておきます。
DataFrameの行を削除する方法を調べると、dropと言う関数がありました。
【公式】pandas.DataFrame.drop
使い方は↓以下の通りです。
DataFrameのIndex番号を指定して削除します。
import pandas as pd
#Excelファイルを読み込む
data_frame = pd.read_excel('{Excelファイルパス}', sheet_name='{シート名}', header=0)
#10行目(Index=9)を削除する場合
data_frame.drop(9)
#6行目(Index=5)と8行目(Index=7)を削除する場合
data_frame.drop([5,7])
#2行目(Index=1)から5行目(Index=4)を削除する場合
data_frame.drop(range(1,4))
今回は表題の通り「取引先が〇〇かつ摘要が△△で始まるデータを削除」と複数の条件を満たす行を削除します。
その為には、条件を満たすIndex番号を取得する必要があります。
DataFrameのIndex番号を取得する方法を調べると、indexと言う関数がありました。
【公式】pandas.DataFrame.index
使い方は↓以下の通りです。
#条件にマッチしたIndexを取得
drop_index = data_frame.index[data_frame['取引先'] == '〇〇']
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
うん、ちゃんと「取引先が〇〇」のデータを削除できました。
次に条件を増やしてみます。
#複数の条件にマッチしたIndexを取得
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'] == '△△*****')]
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
よし、2つの条件のデータは削除できてる!
:
ん?何か忘れてる・・・2つ目の条件は前方一致だった・・・どうやんべか・・・
とりあえず前方一致のstartswithを試してみる。
#DataFrameにstartswithで前方一致を試してみる・・・
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'].startswith('△△'))]
【結果】
Error:'Series' object has no attribute 'startswith'
「Seriesはstartswithを持ってないよ!」と怒られました。
Pandasには、strと言う文字列処理を行えるアクセサ(アクセスメソッド)があり、前方一致で抽出できるstartswith関数もあります。
【公式】pandas.Series.str.startswith
str.startswithで試してみます。
#DataFrameのstrアクセサのstartswithで前方一致の条件を追加
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'].str.startswith('△△'))]
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
お見事!ちゃんと2つの条件のデータが削除できました!
「以上です!」と言いたいところですが、
上記の方法に辿り着くまでに、実は別の方法で実装していました。
#DataFrameの最大行数までの範囲でループ
for i in range(len(data_frame)):
#指定の列と行の値でチャック
if data_frame['取引先'][i] == '〇〇' and data_frame['摘要'][i].startswith('△△'):
#条件にマッチしたIndex番号を削除
data_frame = data_frame.drop(i)
ちょっとアナログな方法ですが、データの行数分をループして1件ごと処理しています。
この方法でも2つの条件のデータをちゃんと削除できます。
他にもいろんな方法がありますが、今回は実際に試した方法を紹介しました。
以上になります。
次回もopenpyxlやpandasを使って苦戦したところを投稿していこうと思います。
ここまで読んで頂き、ありがとうございました。