#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 23 16:14:37 2024

@author: ojacques
"""
import pandas as pd
import numpy as np

#
#P(A|B)=Qtde(A,B)/Qtde(B)
#
#                      Qtde(A,B)       
#          P(A,B)      ---------
#                         n         Qtde(A,B)   
#P(A|B) = -------  = ------------ = ---------
#                      Qtde(B)       Qtde(B)       
#          P(B)       ---------
#                         n
#
#

#-----------repositório de dados http://archive.ics.uci.edu/----------------------

campos=['Classe','Peso Esquerdo','Distância Esquerda', 'Peso Direito','Distância Direita']
caminhoDados='./balance+scale'
#caso o arquivo não tenha nome das colunas ou queira trocar os nomes das colunas utilizar names
df=pd.read_csv(f'{caminhoDados}/balance-scale.data',names=campos) 
qtdeClasse=df['Classe'].value_counts()
prbClasse=qtdeClasse/qtdeClasse.sum()
print(prbClasse)
classes=list(qtdeClasse.index)
numClasses=len(classes)
campos.pop(0) #retira 'Classe'
X=[3,2,1,3]
numAtrib=len(X)

# prbXL=[ df[ (df['Classe']=='L') & (df[campos[i]]==x) ][ [campos[i]] ].count() for i,x in enumerate(X)]/qtdeClasse['L']
# prbXB=[ df[ (df['Classe']=='B') & (df[campos[i]]==x) ][ [campos[i]] ].count() for i,x in enumerate(X)]/qtdeClasse['B']
# prbXR=[ df[ (df['Classe']=='R') & (df[campos[i]]==x) ][ [campos[i]] ].count() for i,x in enumerate(X)]/qtdeClasse['R']

prbXC=np.array([[(df[ (df['Classe']== c) & (df[campos[i]]==x) ]
                [[campos[i]]].count())/qtdeClasse[c] 
                for i,x in enumerate(X)] for c in classes]).reshape(numClasses,numAtrib)
#-----------------------------se nomes dos campos (colunas) não tiverem espaço pode usar query()-----------------------
#prbXC_=np.array([[df.query(f"Classe=='{c}' and {campos[i]}=={x}")[campos[i]].count()/qtdeClasse[c] for i,x in enumerate(X)] for c in classes]).reshape(numClasses,numAtrib)

prbCX=prbClasse*np.prod(prbXC,axis=1) #3 resultados

#----normaliza----------
prbCX=prbCX/np.sum(prbCX)
#Hipotese da Máxima Verossimilhança (HMV)
hMv=np.argmax(prbCX)
#índice do maior argumento para o menor
id=np.argsort(np.array(prbCX))[::-1]
#probabilidade ordenada das classes
prbOrdC=[[classes[cl],prbCX[cl]] for cl in id]
print('--------------PROBABILIDADE DAS CLASSES DADO X-------------------------------')
for l in prbOrdC:
    print(f'Classe {l[0]} = {l[1]:.2f}')

print(f'\n Classe vencedora: {classes[hMv]} probabilidade: {prbCX[hMv]:.2f}')

# prbLX=prbClasse['L']*np.prod(prbXL)
# prbBX=prbClasse['B']*np.prod(prbXB)
# prbRX=prbClasse['R']*np.prod(prbXR)
# prbTot=prbLX+prbBX+prbRX
# prbLX=prbLX/prbTot
# prbBX=prbBX/prbTot
# prbRX=prbRX/prbTot
# print(f'Prob(L): {prbLX:.2f}')
# print(f'Prob(B): {prbBX:.2f}')
# print(f'Prob(R): {prbRX:.2f}')

#--------------------USO DE FILTROS EM COLCHETES OU COM query-------------------------------
# Seja dados de empresas fabricantes de cereais:Kellogs, Nestlé, etc, com os campos:
#  name, mfr, type, calories, protein, fat, sodium, fiber, carbo, sugars, potass, 
#  vitamins, shelf,cups, rating
# Veja aula em https://www.hashtagtreinamentos.com/metodo-query-do-pandas-ciencia-de-dados

#df[df["rating"] > 70]
#df.query("rating > 70")
#df.query("rating > 70")[["name", "rating"]]
#df[(df["mfr"] == "N") & (df["type"] == "H")]
#df.query("mfr == 'N' and type == 'H'")
# df[(df["mfr"] == "N") & ~(df["type"] == "H")]
# df.query("mfr == 'N' and not type == 'H'")
# df[(df["mfr"] == "N") | (df["type"] == "H")]
# df.query("mfr == 'N' or type == 'H'")
# df[df["mfr"].isin(["R", "N", "A"])]
# df.query("mfr in ['R', 'N', 'A']")
# empresas_de_interesse = ["R", "N", "A"]
# df[df["mfr"].isin(empresas_de_interesse)]
# empresas_de_interesse = ["R", "N", "A"]
# df.query("mfr in @empresas_de_interesse")
# df[~df["mfr"].isin(empresas_de_interesse)]
# df.query("mfr not in @empresas_de_interesse")

# train['Sex'].value_counts() #conta a frequência de um único valor
# Out[6]:
# male      577
# female    314
# Name: Sex, dtype: int64
#value_counts()agrega os dados e conta cada valor único. Você pode conseguir o mesmo usando groupbywhich é uma função mais ampla para agregar dados no pandas.
#count()simplesmente retorna o número de valores não NaN/Nulos na coluna (série) em que você o aplica.
#------------------------------Soma----------------------------------------
#data = [[10, 18], [13, 15], [9, 20]]
#df = pd.DataFrame(data)
#somaLinhas=df.sum(axis=0)       #cada linha tem 2 campos, 2 resultados: 32 e 53
#somaLinhas=df.sum(axis='index') #cada index tem 2 campos, 2 resultados: 32 e 53
#somaColunas=df.sum(axis=1)         #cada coluna tem 3 linhas, 3 resultados: 28, 28, 29
#somaColunas=df.sum(axis='columns') #cada coluna tem 3 linhas, 3 resultados: 28, 28, 29




