Подклассы панды фрейма данных для ЭТЛ


Я пишу небольшой ЭТЛ, которая загружает данные из CSV-файлов, чистит каждой таблице немного, а затем загружает все в базу данных PostgreSQL. Я планировал использовать панд для своих встроенных возможностей, но гадаю, стоит ли подкласса таблицы данных или же просто сделать все функционально.

Код таблицы данных подкласса вставляется ниже. Для ремонтопригодность не-программистами, у меня маленький YAML файл с информацией о каждой таблицы и тип столбца.

import pandas
import numpy
import yaml
from os import path

CFG = yaml.load(open('config.yaml', 'r'))

class ETLDataTable(pandas.DataFrame):
    _metadata = ['table_name', 'file_name', 'columns', 'notes']

    @property
    def _constructor(self):
        return ETLDataTable

    def __init__(self, table_name):
        # Name of the database table
        self.table_name = CFG[table_name]['table']
        # Name of the CSV file
        self.file_name = CFG[table_name]['file']
        # Whether file has note fields
        self.notes = CFG[table_name]['notes']

        #Data Types to feed into read_csv
        try:
            self.columns = CFG[table_name]['columns']
        except:
            pass

        _ = path.join(path.abspath(path.pardir), self.file_name)
        super().__init__(pandas.read_csv(_))

    def load_df(self, root_path, **kwargs):
    """Read the csv associated with the table name,
    then import as a pandas DataFrame
    """
        _ = path.join(path.abspath(path.pardir), self.file_name)
        pandas.read_csv(csv_path, 
                        na_values = ['00000000', ' ', ''],
                        encoding="latin1",
                        dtype="object",
                        **kwargs)

В будущем я планировал добавить в некоторые методы, которые необходимы каждой таблицы: фиксация плохих свиданий, обнажая пустые строки и т. д. Такой подход будет больше проблем, чем оно стоит?



Комментарии
1 ответ

Для разбора и анализа моего испытания, я сделал что-то вроде этого:

import pandas as pd
from pathlib import Path

class MyTest:

def __init__(self, settings: dict, root_dir: Path):
self.table_name = settings['table']
self.file_name = settings['file']
...
self.columns = settings.get('columns', None)

filename = root_dir / self.file_name
data = read_data(filename, columns=self.columns)
self._data = fix_data(data)

def summary_x(self):
...
return None

def get_data_between(self, date1, date2):
# optionally parsing the dates
return self._data[self._data['data'].between(date1, date2)]

...

def read_data(filename, **kwargs) -> pd.DataFrame:
return pd.read_csv(
filename,
na_values=['00000000', ' ', ''],
encoding="latin1",
dtype="object",
**kwargs,
)

def fix_data(data: pd.DataFrame, date_cols=None) -> pd.DataFrame:
if date_cols:
date_cols = (date_cols,) if isinstance(date_cols, str) else date_cols
data[date_cols] = [fix_dates(data[col]) for col in date_cols]
...
return data

def fix_dates(data: pd.Series) -> pd.Series:
#optionally a column
pass

def remove_empty_strings(data):
pass

Однажды я был на той стадии, когда мне пришлось несколько типов тестов, я сделал универсальный тип и подкласс этого. Но я не вижу особой ценности в подклассы pandas.Dataframe, потому что тогда вы также должны заботиться, чтобы случайно не перезаписать его методы и атрибуты

2
ответ дан 29 марта 2018 в 10:03 Источник Поделиться