Illustrative example

pydaria - The Data Variability Based Multi-Criteria Assessment Method based on TOPSIS.

Import necessary Python packages and functions and classes from files .py provided in the repository.

[1]:
import os
import copy
import numpy as np
import pandas as pd

from topsis import TOPSIS
from weighting_methods import critic_weighting
from normalizations import minmax_normalization
from additions import rank_preferences

from daria import DARIA

Evaluate each investigated period of a multi-criteria problem using the TOPSIS method.

[2]:
# Temporal alternatives assessment using the DARIA-TOPSIS method based on the Gini coefficient
# variability measure.
# Load the name of the folder with CSV files, including data.
path = 'data'
# Create the list with years to be analyzed that are elements of data files names.
str_years = [str(y) for y in range(2015, 2020)]
# Create a list with latex symbols of evaluated alternatives.
list_alt_names = [r'$A_{' + str(i) + '}$' for i in range(1, 26 + 1)]

# Create dataframes for TOPSIS preferences and rankings for each evaluated year.
preferences = pd.DataFrame(index = list_alt_names)
rankings = pd.DataFrame(index = list_alt_names)

# Evaluate alternatives with the TOPSIS method for each year.
for el, year in enumerate(str_years):
    # Load data from a CSV file for a given year.
    file = 'data_' + str(year) + '.csv'
    pathfile = os.path.join(path, file)
    data = pd.read_csv(pathfile, index_col = 'Country')

    # Create a dataframe with a decision matrix.
    df_data = data.iloc[:len(data) - 1, :]
    df_data = df_data.dropna()

    # Create a vector with criteria types.
    types = data.iloc[len(data) - 1, :].to_numpy()

    #list_of_cols = list(df_data.columns)
    matrix = df_data.to_numpy()
    # Calculate criteria weights using the CRITIC weighting method.
    weights = critic_weighting(matrix)

    # Initialize the TOPSIS method object.
    topsis = TOPSIS(normalization_method=minmax_normalization)
    # Calculate the TOPSIS preferences.
    pref = topsis(matrix, weights, types)
    # Generate the TOPSIS ranking based on calculated preferences.
    rank = rank_preferences(pref, reverse = True)
    # Save the results in dataframes.
    preferences[year] = pref
    rankings[year] = rank

preferences = preferences.rename_axis('Ai')

rankings = rankings.rename_axis('Ai')
[3]:
preferences
[3]:
2015 2016 2017 2018 2019
Ai
$A_{1}$ 0.536617 0.564310 0.564186 0.566951 0.556542
$A_{2}$ 0.336071 0.341904 0.344725 0.352701 0.360289
$A_{3}$ 0.513457 0.532405 0.553370 0.556225 0.572631
$A_{4}$ 0.641617 0.634091 0.633293 0.636302 0.606583
$A_{5}$ 0.560061 0.564331 0.553587 0.556579 0.548127
$A_{6}$ 0.655833 0.655372 0.676693 0.665219 0.680685
$A_{7}$ 0.618126 0.626109 0.631761 0.640734 0.633131
$A_{8}$ 0.428431 0.426274 0.431958 0.455727 0.419436
$A_{9}$ 0.565934 0.577866 0.581817 0.568268 0.560081
$A_{10}$ 0.562669 0.558237 0.573749 0.570323 0.564944
$A_{11}$ 0.374091 0.383914 0.401308 0.417238 0.434746
$A_{12}$ 0.367327 0.407637 0.443797 0.492639 0.475463
$A_{13}$ 0.420014 0.436216 0.452832 0.438847 0.491315
$A_{14}$ 0.465913 0.534756 0.524740 0.556866 0.524790
$A_{15}$ 0.547372 0.542932 0.543019 0.557809 0.570196
$A_{16}$ 0.429350 0.439897 0.446668 0.555374 0.546059
$A_{17}$ 0.552229 0.555966 0.552767 0.541881 0.526681
$A_{18}$ 0.586706 0.605333 0.595225 0.623013 0.606277
$A_{19}$ 0.412392 0.411369 0.422224 0.431644 0.439477
$A_{20}$ 0.461474 0.474797 0.458370 0.470094 0.461408
$A_{21}$ 0.264324 0.263751 0.287022 0.310190 0.328480
$A_{22}$ 0.454640 0.474449 0.501216 0.521071 0.507532
$A_{23}$ 0.444292 0.476562 0.485190 0.540184 0.542270
$A_{24}$ 0.731059 0.755261 0.752157 0.743942 0.755265
$A_{25}$ 0.757916 0.721979 0.722802 0.700069 0.708976
$A_{26}$ 0.584717 0.573694 0.559438 0.537077 0.512966
[4]:
rankings
[4]:
2015 2016 2017 2018 2019
Ai
$A_{1}$ 13 10 9 9 11
$A_{2}$ 25 25 25 25 25
$A_{3}$ 14 15 12 13 7
$A_{4}$ 4 4 4 5 5
$A_{5}$ 10 9 11 12 12
$A_{6}$ 3 3 3 3 3
$A_{7}$ 5 5 5 4 4
$A_{8}$ 20 21 22 21 24
$A_{9}$ 8 7 7 8 10
$A_{10}$ 9 11 8 7 9
$A_{11}$ 23 24 24 24 23
$A_{12}$ 24 23 21 19 20
$A_{13}$ 21 20 19 22 19
$A_{14}$ 15 14 15 11 16
$A_{15}$ 12 13 14 10 8
$A_{16}$ 19 19 20 14 13
$A_{17}$ 11 12 13 15 15
$A_{18}$ 6 6 6 6 6
$A_{19}$ 22 22 23 23 22
$A_{20}$ 16 17 18 20 21
$A_{21}$ 26 26 26 26 26
$A_{22}$ 17 18 16 18 18
$A_{23}$ 18 16 17 16 14
$A_{24}$ 2 1 1 1 1
$A_{25}$ 1 2 2 2 2
$A_{26}$ 7 8 10 17 17

Calculate variability of scores (efficiencies) obtained in particular periods.

[5]:
# applying the DARIA method
# dataframe `preferences` includes preferences of alternatives for evaluated years
df_varia_fin = pd.DataFrame(index = list_alt_names)
# Create a matrix with preference values for each year
# and transpose it to have years in rows and alternatives in columns
df = preferences.T
matrix = df.to_numpy()

# the TOPSIS method orders preferences in descending order
met = 'topsis'

# Calculate efficiencies variability using DARIA methodology
# Initialize the DARIA method object
daria = DARIA()

# Calculate the variability of TOPSIS preferences in all years using the Gini coefficient.
var = daria._gini(matrix)
[6]:
var
[6]:
array([0.00981627, 0.01365081, 0.02084493, 0.0092742 , 0.00558907,
       0.00857705, 0.00663363, 0.01448177, 0.00776515, 0.00546707,
       0.03075309, 0.0582477 , 0.02844171, 0.02944662, 0.01004122,
       0.05927294, 0.01017834, 0.01109442, 0.01425877, 0.00714317,
       0.04823991, 0.0269947 , 0.04172446, 0.00639214, 0.01434414,
       0.02602968])

Calculate variability direction.

[7]:
# Calculate variability directions
dir_list, dir_class = daria._direction(matrix)
[8]:
dir_class
[8]:
array([ 1.,  1.,  1., -1., -1.,  1.,  1., -1., -1.,  1.,  1.,  1.,  1.,
        1.,  1.,  1., -1.,  1.,  1., -1.,  1.,  1.,  1.,  1., -1., -1.])
[9]:
# variability of preference values
df_varia_fin[met.upper() + ' var'] = list(var)
# directions of preferences variability
df_varia_fin[met.upper() + ' dir'] = list(dir_class)

df_varia_fin = df_varia_fin.rename_axis('Ai')
[10]:
df_varia_fin
[10]:
TOPSIS var TOPSIS dir
Ai
$A_{1}$ 0.009816 1.0
$A_{2}$ 0.013651 1.0
$A_{3}$ 0.020845 1.0
$A_{4}$ 0.009274 -1.0
$A_{5}$ 0.005589 -1.0
$A_{6}$ 0.008577 1.0
$A_{7}$ 0.006634 1.0
$A_{8}$ 0.014482 -1.0
$A_{9}$ 0.007765 -1.0
$A_{10}$ 0.005467 1.0
$A_{11}$ 0.030753 1.0
$A_{12}$ 0.058248 1.0
$A_{13}$ 0.028442 1.0
$A_{14}$ 0.029447 1.0
$A_{15}$ 0.010041 1.0
$A_{16}$ 0.059273 1.0
$A_{17}$ 0.010178 -1.0
$A_{18}$ 0.011094 1.0
$A_{19}$ 0.014259 1.0
$A_{20}$ 0.007143 -1.0
$A_{21}$ 0.048240 1.0
$A_{22}$ 0.026995 1.0
$A_{23}$ 0.041724 1.0
$A_{24}$ 0.006392 1.0
$A_{25}$ 0.014344 -1.0
$A_{26}$ 0.026030 -1.0

Calculate final aggregated alternatives efficiencies considering variability var (G), performance values from the most recent period S and variability direction dir.

[11]:
df_final_results = pd.DataFrame(index = list_alt_names)

# S = preferences['2019'].to_numpy()
S = matrix[-1, :]
G = copy.deepcopy(var)
dir = copy.deepcopy(dir_class)

# Update efficiencies using DARIA methodology.
# final updated preferences
final_S = daria._update_efficiency(S, G, dir)
[12]:
final_S
[12]:
array([0.56635855, 0.37394021, 0.59347605, 0.59730846, 0.54253799,
       0.68926166, 0.63976447, 0.40495374, 0.55231592, 0.57041145,
       0.4654987 , 0.53371068, 0.51975682, 0.55423646, 0.58023707,
       0.60533184, 0.51650296, 0.61737164, 0.45373564, 0.4542645 ,
       0.37671978, 0.53452679, 0.5839945 , 0.76165676, 0.69463228,
       0.48693636])

Rank the alternatives in descending order, like in TOPSIS (the best alternative has the highest value of efficiency).

[13]:
# The TOPSIS ranking is prepared in descending order according to prefs.
rank = rank_preferences(final_S, reverse = True)
[14]:
rank
[14]:
array([12, 26,  8,  7, 15,  3,  4, 24, 14, 11, 21, 17, 18, 13, 10,  6, 19,
        5, 23, 22, 25, 16,  9,  1,  2, 20])
[15]:
# Save aggregated final preference values and rankings.
df_final_results[met.upper() + ' pref'] = final_S
df_final_results[met.upper() + ' rank'] = rank
df_final_results = df_final_results.rename_axis('Ai')
[16]:
df_final_results
[16]:
TOPSIS pref TOPSIS rank
Ai
$A_{1}$ 0.566359 12
$A_{2}$ 0.373940 26
$A_{3}$ 0.593476 8
$A_{4}$ 0.597308 7
$A_{5}$ 0.542538 15
$A_{6}$ 0.689262 3
$A_{7}$ 0.639764 4
$A_{8}$ 0.404954 24
$A_{9}$ 0.552316 14
$A_{10}$ 0.570411 11
$A_{11}$ 0.465499 21
$A_{12}$ 0.533711 17
$A_{13}$ 0.519757 18
$A_{14}$ 0.554236 13
$A_{15}$ 0.580237 10
$A_{16}$ 0.605332 6
$A_{17}$ 0.516503 19
$A_{18}$ 0.617372 5
$A_{19}$ 0.453736 23
$A_{20}$ 0.454264 22
$A_{21}$ 0.376720 25
$A_{22}$ 0.534527 16
$A_{23}$ 0.583994 9
$A_{24}$ 0.761657 1
$A_{25}$ 0.694632 2
$A_{26}$ 0.486936 20
[ ]: