ファイル整理の自動化① ファイルパス取得、ファイルのコピー・削除
せっかくPythonをローカル環境で使用できるようになったので、日常の定型業務を自動化してみましょう!
やりたい事(条件)
フォルダAの中にある「■rawData」というフォルダに、1日1ファイルずつ日報ファイル(Excel)がたまっていきます。
1ヶ月経過したら、1ヶ月分のデータを1つのExcelファイルになるようにまとめて集計ファイルを作成(「yyyymm集計データ.xlsx」、yyyyとmmには西暦年と月が入ります)し、フォルダAの中にある「■集計データ」フォルダに保存します。
集計が終わったら、フォルダAの直下に「yyyymm」のフォルダを作成し、「■rawData」内にある元データを移して「■rawData」を空にします。
準備
年月の処理(yyyymm)
毎月1日にとあるプログラムを自動実行して、上記の操作を行えば良いということになります。
ファイル名やフォルダ名にyyyymmの情報が必要になるので準備します。
import datetime
today = datetime.datetime.today()
todayという変数の中に、実行時の年月日時分秒のデータが格納されます。
print(today.year)
print(today.month)
> 2024
5
today.yearやtoday.monthとすることで、年や月をint型(整数)で取得することができます。
先月分のデータを処理するので、today.month -1で先月を表現できます。ただし、todayが1月だった場合は先月が「0月」となってしまうので、if文で条件分岐を作成し「12月」となるように対処します。
また、月が1桁のときは0埋めして「5」→「05」のようにした方が1月から12月のファイル・フォルダがきれいに並びます。zfill( 桁数 )を使用することで引数に指定した桁数になるように0で埋めてくれます。
print(today.month)
print(str(today.month))
print(str(today.month).zfill(2))
> 5 ←int
'5' ←str
'05' ←str(2桁になるように0埋め)
実際は毎月1日に自動実行し、上記のtodayを取得するコードを使用しますが、以降のコードを作成する都合上todayを2024/6/1としてyyyymmを作成しています。
today = datetime.datetime(2024, 6, 1, 0, 0, 0, 0)
if today.month == 1:
yyyymm = str(today.year -1) + '12'
else:
yyyymm = str(today.year) + str(today.month -1).zfill(2)
print(yyyymm)
> '202405'
today(2024/6/1)から先月を示すyyyymmを作成できました。
ファイルパスの定義
元データが入っているフォルダ、集計データを出力するフォルダ、処理後の元データを保存するフォルダ(実行時に作成される)を以下のように変数に入れて準備しておきます。
src_path = "C:\\Users\\*******\\フォルダA\\■rawData\\"
output_path = "C:\\Users\\*******\\フォルダA\\■集計データ\\"
dst_path = f"C:\\Users\\*******\\フォルダA\\{yyyymm}"
ファイルの結合
ファイルの結合はconcatを使用し縦方向に結合していけば良さそうです。concatに関しては以下をご参照ください。
「■rawData」フォルダの中にあるExcelファイル名(ファイルパス)を取得できれば、順次DataFrameにしてconcatで結合していくループ処理を書けそうです。
ファイルパスを取得する方法はいくつかありますが、今回はglobを使用します。
import glob
files = glob.glob(src_path + '*.xlsx')
src_path(「■rawData」フォルダ)に含まれる「.xlsx」拡張子をもつファイルをリストで取得できます。「*」はワイルドカードで「何かしらの文字列」を意味しています。
filesにはファイルパス(正確には「.xlsx」を拡張子とするファイルのパス)がリストとして格納されているので、インデックス番号を指定することでファイルパスを取り出すことができます。
import pandas as pd
df1 = pd.read_excel(files[0])
for i in range(1, len(files)):
df2 = pd.read_excel(files[i])
df1 = pd.concat([df1, df2])
files[0]でdf1を作成し、そこにdf2をconcatで結合しdf1を上書きしていきます。for文でループ処理をしていきますが、range(1, len(files))としてループするのは2番目(インデックス番号としては1)以降のファイルパスであることに注意してください。
for文が終了すると全てのExcelファイルが結合したdf1が完成します。あとは、DataFrameをExcelファイルに変換して保存するだけです。
df1.to_excel(output_path + f'{yyyymm}集計データ.xlsx', index=False)
これで、output_path(フォルダAの中の■集計データ)に「202405集計データ.xlsx」というExcelファイルが作成されているハズです。
ファイルの移動(コピー)
次に、日ごとの生データを任意のフォルダにコピーします。コピーにはshutilを使用します。shutilを使うことでファイルやフォルダのコピー・移動ができます。
copy(src, dst):src(source、コピー元)からdst(destination、コピー先)にファイルをコピーします。同名のファイルは上書きされます。
copytree(src, dst, dirs_exist_ok=True):srcファルダ内のファイルをdstフォルダへコピーします。実行時にdstフォルダが作成されるため、既にフォルダが存在するとエラーとなります。dirs_exist_okをTrueにしておくと、既にフォルダが存在してもエラーにならない。
move(src, dst):ファイルまたはディレクトリ(src)を再帰的に別の場所に移動します。
今回は「■rawData」内の複数ファイルのみ移したいのでcopytree()を使用しています。
import shutil
shutil.copytree(src=src_path,
dst = dst_path,
dirs_exist_ok=True
)
コピー先は、f-stringでyyyymmの日付が入ったフォルダが毎回作成されます。一応、同名のフォルダが存在したとしてもエラーが出ないようdirs_exist_ok=Trueとしています。
元のフォルダ内のファイルを削除
osモジュールを使用すれば、OSに依存しているさまざまな機能を利用できます。先ほどglobを使用してファイルパスを取得しましたが、osを使用してパスを取得することもあります。
remove( 削除したいファイルのパス )を使用することで、指定のファイルを削除することができます。filesの中にファイルパスがリストで格納されているので、for文を使って順番に消していくことができます。
import os
for file in files:
os.remove(file)
以上でミッションを完了することができます。osモジュールを使用してファイルパスを取得すれば、globをimportする必要はなくなりますコードがスッキリするかもしれません。ファイル操作に関連するモジュールも複数あり、使ってみて操作方法を知っておくと良さそうです。
今回は単純なファイルの結合とファイル移動だけでしたが、1ヶ月分のデータが揃えば可視化してみたくなりますよね!これまでの投稿で紹介したAltairやmatplotlibなどを使用して、まとめたデータをグラフ化するコードも追記すれば所定のフォルダに日報を入れておけば、何もしなくても毎月1日には自動でファイルがまとめられグラフ化(さらにはレポート出力も!)されます。ファイルを一つ一つ手動でコピペして…なんで面倒なだけですね。それよりは、出力されたデータ分析に労力を割く方がよっぽど有意義です。
今回はコードを作成したので、次回は何もしなくても実行されるよう設定していきたいと思います。お楽しみに!