#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This file is part of the
# Apode Project (https://github.com/ngrion/apode).
# Copyright (c) 2020, Néstor Grión and Sofía Sappia
# License: MIT
# Full Text: https://github.com/ngrion/apode/blob/master/LICENSE.txt
# =============================================================================
# DOCS
# =============================================================================
"""ApodeData class for Apode."""
# =============================================================================
# IMPORTS
# =============================================================================
import attr
import pandas as pd
from .concentration import ConcentrationMeasures
from .inequality import InequalityMeasures
from .plots import PlotAccessor
from .polarization import PolarizationMeasures
from .poverty import PovertyMeasures
from .welfare import WelfareMeasures
# =============================================================================
# MAIN CLASS
# =============================================================================
[docs]@attr.s(frozen=True, repr=False)
class ApodeData:
"""Poverty and Inequality Analysis in Python.
Apode is a package that contains a set of indicators that are applied in
economic analysis. It contains measures of:
- poverty
- inequality
- welfare
- polarization
- concentration
Parameters
----------
data : dataframe
Dataset to be analiced.
income_column : str
Column name
Attributes
----------
data, income_column : see Parameters
"""
data = attr.ib(converter=pd.DataFrame)
income_column = attr.ib()
poverty = attr.ib(
init=False, default=attr.Factory(PovertyMeasures, takes_self=True)
)
inequality = attr.ib(
init=False, default=attr.Factory(InequalityMeasures, takes_self=True)
)
polarization = attr.ib(
init=False, default=attr.Factory(PolarizationMeasures, takes_self=True)
)
concentration = attr.ib(
init=False,
default=attr.Factory(ConcentrationMeasures, takes_self=True),
)
welfare = attr.ib(
init=False, default=attr.Factory(WelfareMeasures, takes_self=True)
)
plot = attr.ib(
init=False, default=attr.Factory(PlotAccessor, takes_self=True)
)
@income_column.validator
def _validate_income_column(self, name, value):
if value not in self.data.columns:
raise ValueError()
@data.validator
def _validate_data(self, name, value):
if self.data.empty:
raise ValueError()
def __getattr__(self, aname):
"""Apply DataFrame method."""
return getattr(self.data, aname)
def __getitem__(self, slice):
"""Apply Slice method."""
data = self.data.__getitem__(slice)
if not hasattr(data, self.income_column):
raise AttributeError(
f"Cannot take column {self.income_column} "
"from ApodeData object"
)
return ApodeData(data, income_column=self.income_column)
def __repr__(self):
"""Apply Display method."""
with pd.option_context("display.show_dimensions", False):
df_body = repr(self.data).splitlines()
footer = self._get_footer()
brepr = "\n".join(df_body + [footer])
return brepr
def _repr_html_(self):
with pd.option_context("display.show_dimensions", False):
df_html = self.data._repr_html_()
ad_id = id(self)
footer = self._get_footer(html=True)
parts = [
f'<div class="apode-data-container" id={ad_id}>',
df_html,
footer,
"</div>",
]
html = "".join(parts)
return html
def _get_footer(self, html=None):
income_column = self.income_column
if html is True:
income_column = f"<i>{income_column}</i>"
rows = f"{self.data.shape[0]} rows"
columns = f"{self.data.shape[1]} columns"
footer = f"ApodeData(income_column='{income_column}') - {rows} x \
{columns}"
return footer
def __dir__(self):
"""Allow access to methods and attributes of the dataframe."""
return super().__dir__() + dir(self.data)