wolf4032's picture
Add docstring
e485999 verified
raw
history blame
6.43 kB
import pandas as pd
import numpy as np
import ast
from abc import ABC, abstractmethod
from typing import List, Any
def read_csv_df(read_path: str, header: int = 0) -> pd.DataFrame:
"""
csv形式のデータフレームの読み込み
文字列として読み込まれたリストの復元も行う
Parameters
----------
read_path : str
データフレームが保存されているパス
header : int, optional
ヘッダーとする行の指定, by default 0
Returns
-------
pd.DataFrame
データフレーム
"""
df = pd.read_csv(read_path, header=header)
lst_col_names = df.columns[df.iloc[0].apply(check_lst_col)]
df[lst_col_names] = df[lst_col_names].applymap(ast.literal_eval)
return df
def check_lst_col(value: str) -> bool:
"""
リストの列の確認
元の値がリストだった列の確認
Parameters
----------
value : str
その列の代表の値
Returns
-------
bool
その列の値がリストならTrue、リストでなければFalse
"""
# 数値に、インデックスで最初の文字を指定するとエラーになる
is_str = isinstance(value, str)
# 空文字に、インデックスで最初の文字を指定するとエラーになる
is_not_empty = len(value) > 0
is_lst = value[0] == '['
is_lst_col = is_str and is_not_empty and is_lst
return is_lst_col
def save_csv_df(df: pd.DataFrame, file_name: str, save_dir: str) -> None:
"""
csv形式でのデータフレームの保存
Parameters
----------
df : pd.DataFrame
保存するデータフレーム
file_name : str
保存するデータフレームのファイル名
save_dir : str
データフレームの保存先ディレクトリ
"""
df.to_csv(f'{save_dir}/{file_name}.csv', index=False)
class CustomError(Exception, ABC):
"""
カスタムエラーの基底クラス
"""
def __init__(self, occurred_error: Exception, *message_args: Any):
"""
CustomErrorのコンストラクタ
Parameters
----------
occurred_error : Exception
発生したエラー
"""
self.message_first_line = f'エラーが発生しました: {occurred_error}'
self.message = self.create(*message_args)
super().__init__(self.message)
@abstractmethod
def create(self, *message_args: Any) -> str:
"""
エラーメッセージを作成するメソッド
Returns
-------
str
エラーメッセージ
"""
pass
def create_multi_line_message(self, lines: List[str]) -> str:
"""
規定の文字列を先頭に付けて、エラーメッセージを改行させるメソッド
Parameters
----------
lines : List[str]
エラーメッセージの各行の内容を持つリスト
Returns
-------
str
エラーメッセージ
"""
lines = [self.message_first_line] + lines
message = '\n\t'.join(lines)
return message
class ColumnNameError(CustomError):
"""
存在しない列名を渡した際に起きるカスタムエラーのクラス
"""
def create(self, col_name: str) -> str:
"""
エラーメッセージを作成するメソッド
Parameters
----------
col_name : str
存在しなかった列名
Returns
-------
str
エラーメッセージ
"""
lines = [
f'"{col_name}"という列は見つかりませんでした',
'列名を変更するか、番号で列を指定してください'
]
message = self.create_multi_line_message(lines)
return message
class DataframeIndexError(CustomError):
"""
存在しないインデックスを指定した際に起きるカスタムエラーのクラス
"""
def create(self, df: pd.DataFrame) -> str:
"""
エラーメッセージを作成するメソッド
Parameters
----------
df : pd.DataFrame
データフレーム
Returns
-------
str
エラーメッセージ
"""
rows_len = len(df)
cols_len = len(df.columns)
lines = [
f'このデータフレームは、{rows_len}{cols_len}列です',
f'row_idxは{rows_len - 1}、colは{cols_len - 1}以下にしてください'
]
message = self.create_multi_line_message(lines)
return message
def get_col_idx(df: pd.DataFrame, col_name: str) -> int:
"""
列名から、その列のインデックスを取得するメソッド
Parameters
----------
df : pd.DataFrame
インデックスを取得するデータフレーム
col_name : str
インデックスを取得する列名
Returns
-------
int
列のインデックス
Raises
------
ColumnNameError
存在しない列名
"""
try:
col_idx = df.columns.values.tolist().index(col_name)
except ValueError as e:
raise ColumnNameError(e, col_name)
return col_idx
def update_row(
df: pd.DataFrame, row_idx: int, col_idx_or_name: int | str,
value: Any) -> None:
"""
指定した一つのセルの値を更新するメソッド
Parameters
----------
df : pd.DataFrame
更新対象のデータフレーム
row_idx : int
更新するセルの行インデックス
col : int | str
更新するセルの列インデックスか、列名
value : Any
セルに入れる値
Raises
------
ColumnNameError
存在しない列名
DataframeIndexError
存在しないインデックス
"""
if isinstance(col_idx_or_name, str):
col_name = col_idx_or_name
if col_name not in df.columns:
raise ColumnNameError('カスタムエラー', col_name)
df.at[row_idx, col_name] = value
else:
col_idx = col_idx_or_name
try:
df.iat[row_idx, col_idx] = value
except IndexError as e:
raise DataframeIndexError(e, df)