概要
Pythonでやった作業について,忘れないようまとめます。
※Pythonの学習中に行ったことなので、もっと便利な関数や手法があるかもしれません。
ファイルパスの操作(OSモジュールを使用)
ファイル名(拡張子付き)の取り出し
import os
fpath="aaa/bbb/ccc/ddd.png"
fname=os.path.basename(fpath)
# ddd
ファイル名(拡張子なし)の取り出し
import os
fpath="aaa/bbb/ccc/ddd.png"
fname=os.path.splitext(os.path.basename(fpath))[0]
# ddd
拡張子のみの取り出し
import os
fpath="aaa/bbb/ccc/ddd.png"
fname=os.path.splitext(os.path.basename(fpath))[1]
# .png
ディレクトリパスの取り出し
import os
fpath="aaa/bbb/ccc/ddd.png"
fname=os.path.dirname(fpath)
# aaa/bbb/ccc
ファイルパスからファイル名のみを抜き出す(OSモジュールを使用せず)
splitを使う
fpath="aaa/bbb/ccc/ddd.png"
f_split=fpath.split('/')
fname=f_split[-1]
split()
で区切り文字で分割,分割した配列の最後がファイル名.
区切り文字はあらかじめ調べるor決める必要がある
参考:javascript(nodejs)でフルパスからファイル名のみを取得する方法 - Nodachisoft
正規表現を使う
import re
fpath="aaa/bbb/ccc/ddd.png"
m = re.match(r".+[\\/](.+?)([-_.]*)?$",fpath)
print(m[1])
# ddd.png
参考:Pythonでパス文字列からファイル名・フォルダ名・拡張子を取得、結合 | note.nkmk.me
ファイル読み書きテンプレ
JSON
#.jsonの読み取り
import json
with open("test_r.json","r",encoding="utf-8") as f:
d_read=json.load(f)
#.jsonへ書き込み
with open("test_w.json", 'w',encoding="utf-8") as f:
json.dump(d_write, f, indent=2,ensure_ascii=False)
保存時、indent
を付けることでインデントが付き、ensure_ascii
DataFrameのよく使う?操作
NaN埋め、型変換
指定した列のみを型変換する場合
l_cols=['A','B','C']
d_rep={}
for col in ctg_columns:
d_rep[col]=str
df=df.astpye(d_rep)
列名:型
の辞書型を作成し、.astype
に指定する。
.fillna
も同じ手法でできる
l_cols=['A','B','C']
d_rep={}
for col in ctg_columns:
d_rep[col]=0
df=df.fillna(d_rep)
df.groupbyをグループごとにfor文で回す
import pandas as pd
for idx,df_group in df.groupby(["馬番","着順"]):
# 何かの処理
print(idx)
正規表現の利用
正規表現で途中にある数値を取得
re.search
を使うことで文字列の途中からマッチする。
import re
fname="hogehoge24.png"
m=re.match(r"[0-9]{1,2}",fname)
print(m[0])
#24
ファイル名のパターンが決まっているなら、間の文字列を抜き出すことでも取り出せる。
「(.+)」で任意の1文字以上の文字列にマッチする。
import re
fname="hogehoge24.png"
m=re.match(r"[0-9]{1,2}",fname)
m=re.search(r"hogehoge(.+)\.png",fname)
print(m[1])
#24
re.match
だと先頭からのマッチとなり、途中にあるパターンを抜き出せない。
参考:【python】re.match より re.search を使おう
正規表現でファイルの拡張子を取り除く方法。
datetimeをdatetimeに変換
Javascriptから取得した時刻をPythonのdatetimeに変換する
import re
from datetime import datetime
time_JS="2022-12-28T12:58:30+09:00"
# 年・月・日を取得
m=re.search("([0-9]{4})-([0-9]{2})-([0-9]{2})",time_JS)
# 時・分・日を取得
m2=re.search("([0-9]{2}):([0-9]{2}):([0-9]{2})",time_JS)
# Pythonのdatetimeに変換
res_datetime=datetime(int(m[1]),int(m[2]),int(m[3]),int(m2[1]),int(m2[2]),int(m2[3]))
print(res_datetime)
Excelファイルの処理
DataframeをXlsxファイルへと書き出す
複数のDataFrameをXlsxに出力するクラス
クラス内変数の辞書型配列に、Key=シート名、中身=保存したいDataFrameで登録した情報をもとにxlsxファイルを作成します。
class exportXlsx:
def __init__(self) -> None:
self.dict_array={
}
pass
def addSheet(self,item,sname):
# シート名としてDFを保存する
self.dict_array[sname]=item
def save(self,savefpath):
# 登録したDFを保存する
dict_keys=list(self.dict_array.keys())
# 先頭のシートで上書き
logger.info("save:"+savefpath)
logger.debug("save:"+dict_keys[0])
self.dict_array[dict_keys[0]].to_excel(savefpath,index=False,sheet_name=dict_keys[0])
# 残りのシートを追加
with pd.ExcelWriter(savefpath, mode='a') as writer:
for key in sorted(dict_keys[1:]):
self.dict_array[key].to_excel(writer,index=False,sheet_name=key)
logger.debug("save:"+key)
使い方
- このクラスのインスタンスを作成
- 保存したいDataFrameを
addSheet
メソッドで追加する
2.item
:保存するDataFrame
2.key
:保存するシート名。ユニークかつ30文字以内、シート名で使えない文字を除く。 - すべてのDataFrameを登録したら、
save
メソッドを実行。
2.savefpath
:保存するファイルパスを入れる。
import pandas as pd
import exportXlsx
df1=pd.DataFrame()
df2=pd.DataFrame()
# ~~df1,df2に中身を入れる~~
expXlsx=exportXlsx.exportXlsx()
# 保存するDataFrameの登録
expXlsx.addSheet(df1,"sheetname1")
expXlsx.addSheet(df2,"sheetname2")
# 保存
expXlsx.save("sample.xlsx")
Xlsxに色付け・線引き
DataFrameのIndex,列を指定したセルに色づけをする
def setCellColor(sheet,df,l_idx,colname,fill):
# 指定されたセルに色を付ける
# l_idx=df.index
col_idx=df.columns.tolist().index(colname)
for row_idx in l_idx:
# print(row_idx,get_column_letter(col_idx))
# excelでは行は1始まり&1行目は列名なので+2、列番号も1始まりなので+1
sheet.cell(row=int(row_idx)+2,column=int(col_idx)+1).fill=fill
return sheet
def setBorderLine(sheet,df,l_idx,border):
# 指定されたセルに色を付ける
for row_idx in l_idx:
for col_idx in range(sheet.min_column,sheet.max_column):
sheet.cell(row_idx+1+1,col_idx).border=border
return sheet
GPX(xml)を処理し、座標データをDataframeにする
やったこと:StravaのGPXデータから,GoogleMapから取得した座標データと最も近い点を求め,そこを通過した時刻を出力
実装概要
- ElementTreeによるxmlデータの読み込み
- 緯度・経度・時刻をDataframeに格納
- Dataframeと指定した緯度・経度を比較し最も近い値の時刻を出力
Pythonによるxmlの読み込み
xml.etree.ElementTreeという標準ライブラリを使う.
https://qiita.com/sino20023/items/0314438d397240e56576
https://pg-chain.com/python-xml-elementtree
import xml.etree.ElementTree as ET
tree = ET.parse('_3776_day1_.xml')
root = tree.getroot()
# root[0]:<metadata>,root[1]:<trk>.root[1]の2つ目?を↓で取り出す.
tree_trkseg = root[1][2]
for child in tree_trkseg:
print(child.attrib['lat'],child.attrib['lon'],child[1].text)
このFor文によって、緯度・経度・時刻を抜き出すことができる。
必要なデータをDataframeに格納
緯度・経度・時間の3つを格納したDataframeの作成
df_cdata = pd.DataFrame(columns=['lat','lon','time'])
for child in tree_trkseg:
# lat(緯度)lon(経度)time(時間)をデータフレームに格納
df_cdata=df_cdata.append(pd.Series([child.attrib['lat'],child.attrib['lon'],child[1].text],index=df_cdata.columns),ignore_index=True)
1行目で空のDataframeを作成、2行目のFor文で緯度・経度・時刻の入ったpd.Seriesを作成し、1行目のDataframeにappendします。
指定した座標とマッチング
緯度・経度ともにDataframeから最も近い値をそれぞれ探し,その時刻を出力します.
こちらのサイトを参考に、入力した値から一番差が少ないDataframeの行を出力しました。
https://funmatu.wordpress.com/2018/10/01/pandas-dataframe%E5%86%85%E3%81%8B%E3%82%89%E6%9C%80%E3%82%82%E8%BF%91%E3%81%84%E5%80%A4%E3%82%92%E6%8E%A2%E3%81%99/
l_lat = df['lat'].sub(SEARCHLAT).abs().argsort()[:5]
l_lon = df['lon'].sub(SEARCHLON).abs().argsort()[:5]
for i in l_lat:
print(i,df['time'][i])
print("===============================")
for i in l_lon:
print(i,df['time'][i])
緯度・経度で別々の行が出力されるため,近い順に5行の時刻を出力した後、最も近い(と思われる)値を参考にしました。