#!/usr/bin/env python
# coding: utf-8

# # Visualização de dados com _seaborn_

# No capítulo [Plotagem e formatação de gráficos](09-plotagem-matplot.ipynb), fizemos uma breve introdução à _visualização de dados_ e aprendemos a utilizar o _matplotlib_ para realizar plotagens básicas de gráficos. Neste capítulo, exploraremos a visualização de dados utilizando o módulo _seaborn_.
#
# O _seaborn_ estende as potencialidades do _matplotlib_ em, praticamente, dois aspectos: i) provendo melhor estilização dos gráficos e tornando-os visualmente "belos"; ii) compactando funções de plotagem do _matplotlib_, de modo que plotagens robustas sejam obtidas com menos instruções de código.

# Vamos começar importando as bibliotecas que utilizaremos.

# In[1]:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

import warnings
warnings.filterwarnings('ignore')

# Vamos reconstruir e importar alguns *DataFrames*.

# In[2]:

serie_Idade = pd.Series({'Ana':20, 'João': 19, 'Maria': 21, 'Pedro': 22, 'Túlio': 20}, name="Idade")
serie_Peso = pd.Series({'Ana':55, 'João': 80, 'Maria': 62, 'Pedro': 67, 'Túlio': 73}, name="Peso")
serie_Altura = pd.Series({'Ana':162, 'João': 178, 'Maria': 162, 'Pedro': 165, 'Túlio': 171}, name="Altura")

# In[3]:

dicionario_series_exemplo = {'Idade': serie_Idade, 'Peso': serie_Peso, 'Altura': serie_Altura}

# In[4]:

df_dict_series = pd.DataFrame(dicionario_series_exemplo);df_dict_series

# In[5]:

df_exemplo = pd.read_csv('../database/exemplo_data.csv', index_col=0)
df_exemplo['coluna_3'] = pd.Series([1,2,3,4,5,6,7,8,np.nan,np.nan],index=df_exemplo.index)
df_exemplo.index = pd.to_datetime(df_exemplo.index)
df_exemplo

# In[6]:

covid_PB = pd.read_csv('https://superset.plataformatarget.com.br/superset/explore_json/?form_data=%7B%22slice_id%22%3A1550%7D&csv=true',
                             sep=',', index_col=0)
covid_PB.head()

# In[7]:

covid_BR = pd.read_excel('../database/HIST_PAINEL_COVIDBR_25jul2020.xlsx')
covid_BR.head()

# ## Gráficos de Linha e de Dispersão
#
# Através da função `relplot`, podemos alterar o valor do parâmetro `kind` para
# obter gráficos do linha, com `kind = 'line'`, ou gráficos de dispersão, com `kind  = 'scatter'`. De modo alternativo, poderíamos também utilizar as funções `lineplot` e `scatterplot`. Entretanto, com `relplot`, diversos elementos de construção de figura existentes no *matplotlib* já são pré-configurados no _seaborn_. Isto é chamado no *seaborn* de *figure-level plot*.

# Inicialmente, vejamos como a função `lineplot` se comporta como qualquer outra do `matplotlib.pyplot`.

# In[8]:

fig, ax = plt.subplots()
ax = sns.lineplot(x="index", y="coluna_1", data=df_exemplo.reset_index(), label = 'Coluna 1')
ax = sns.lineplot(x="index", y="coluna_2", data=df_exemplo.reset_index(), label = 'Coluna 2')
ax = sns.lineplot(x="index", y="coluna_3", data=df_exemplo.reset_index(), label = 'Coluna 3')
ax.set_xlabel('Data')
ax.set_ylabel('Valor')
fig.autofmt_xdate() # auto-formata xticks tipo "data"

# Para utilizar a função `relplot`, precisaremos reorganizar o banco de dados de modo que haja apenas uma coluna de valores no eixo _y_ (`Valor`) e uma coluna com um identificador de cor/tonalidade (`Coluna`).

# In[9]:

# reorganiza para 'Coluna 1'
df_exemplo_px = pd.DataFrame(df_exemplo['coluna_1']).rename({'coluna_1':'Valor'}, axis=1)
df_exemplo_px['Coluna'] = 'Coluna 1'

# concatena 'Coluna 2'
df_exemplo_px_temp = pd.DataFrame(df_exemplo['coluna_2']).rename({'coluna_2':'Valor'}, axis=1)
df_exemplo_px_temp['Coluna'] = 'Coluna 2'
df_exemplo_px = pd.concat([df_exemplo_px, df_exemplo_px_temp])

# concatena 'Coluna 3'
df_exemplo_px_temp = pd.DataFrame(df_exemplo['coluna_3']).rename({'coluna_3':'Valor'}, axis=1)
df_exemplo_px_temp['Coluna'] = 'Coluna 3'
df_exemplo_px = pd.concat([df_exemplo_px, df_exemplo_px_temp])

df_exemplo_px.head()

# In[10]:

# 'hue' atribui as tonalidades de cor com base no identificador
p = sns.relplot(x = 'index', y='Valor', hue = 'Coluna', data=df_exemplo_px.reset_index().dropna(), kind='line')
p.fig.autofmt_xdate()
p.ax.set_xlabel('Data')
p.fig.set_size_inches(8,4) # largura, altura

# Vamos agora plotar o gráfico de óbitos por COVID-19 na Paraíba juntamente com a média aritmética móvel de 7 dias e com a média geométrica móvel de 7 dias.
#
# Utilizaremos o método `rolling` de uma *Series* ou *DataFrame* do *pandas*. Este método cria janelas móveis onde podemos aplicar uma função agregadora (tal como média ou média geométrica).

# Comentários:
#
# - A média aritmética tem a desvantagem de linearizar o efeito do crescimento ou decrescimento do número de óbitos, onde sabemos que o efeito é exponencial.
# - A média geométrica móvel tem a desvantagem de se anular se o número de óbitos em algum dos dias da janela for zero.
# - Em geral, as duas médias ficam muito próximas.

# In[11]:

# função que calcula a média geométrica
from scipy.stats import gmean

# série
covid_PB_obitos = covid_PB.obitosNovos
covid_PB_obitos = covid_PB_obitos.sort_index()
covid_PB_obitos.name = 'Óbitos'

# dataframe
covid_PB_obitos_df = pd.DataFrame(covid_PB_obitos)
covid_PB_obitos_df['Tipo'] = 'Valor nominal'

# média aritmética móvel
covid_PB_obitos_df_temp = pd.DataFrame(covid_PB_obitos.rolling(7).mean().dropna())
covid_PB_obitos_df_temp['Tipo'] = 'MM:arit - 7d'
covid_PB_obitos_df = pd.concat([covid_PB_obitos_df, covid_PB_obitos_df_temp])

# média geométrica móvel
covid_PB_obitos_df_temp = pd.DataFrame(covid_PB_obitos.rolling(7).aggregate(gmean).dropna())
covid_PB_obitos_df_temp['Tipo'] = 'MM:geom - 7d'
covid_PB_obitos_df = pd.concat([covid_PB_obitos_df, covid_PB_obitos_df_temp])

covid_PB_obitos_df.index = pd.to_datetime(covid_PB_obitos_df.index)

covid_PB_obitos_df.tail()

# In[12]:

p = sns.relplot(x = 'data', y='Óbitos',
                hue = 'Tipo',
                data=covid_PB_obitos_df.reset_index(),
                kind='line')
p.fig.autofmt_xdate()
p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Vamos agora construir um gráfico de dispersão com o _DataFrame_ `df_exemplo_px`.

# In[13]:

# 'scatter' é padrão
p = sns.relplot(x = 'index', y='Valor',
                hue = 'Coluna',
                data=df_exemplo_px.reset_index().dropna())
p.fig.autofmt_xdate()
p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Vamos forçar os limites de datas a ficarem dentro do mínimo (menos um dia) e do máximo (mais um dia):

# In[14]:

p = sns.relplot(x = 'index', y='Valor',
                      hue = 'Coluna',
                      data=df_exemplo_px.reset_index().dropna())

# offset de data
p.ax.set_xlim((df_exemplo_px.reset_index()['index'].min()
               - pd.DateOffset(days=1)),
              (df_exemplo_px.reset_index()['index'].max()
               + pd.DateOffset(days=1)))

p.fig.autofmt_xdate()
p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# In[15]:

# especifica cores e tamanhos
p = sns.relplot(x = 'index', y='coluna_1',
                hue = 'coluna_2',
                size = 'coluna_3',
                data=df_exemplo.reset_index().dropna())

p.ax.set_xlim((df_exemplo.reset_index()['index'].min()
               - pd.DateOffset(days=1)),
              (df_exemplo.reset_index()['index'].max()
               + pd.DateOffset(days=1)))

p.fig.autofmt_xdate()
p.ax.set_xlabel('')
p.fig.set_size_inches(8,4)

# In[16]:

covid_PB_casos_obitos = covid_PB[['obitosNovos', 'casosNovos']].sort_index()
covid_PB_casos_obitos.index = pd.to_datetime(covid_PB_casos_obitos.index)

# cor: óbitos novos
p = sns.relplot(x = 'data', y = 'casosNovos',
                hue = 'obitosNovos',
                data=covid_PB_casos_obitos.reset_index())

p.ax.set_xlim((covid_PB_casos_obitos.reset_index()['data'].min()
               - pd.DateOffset(days=5)),
              (covid_PB_casos_obitos.reset_index()['data'].max()
               + pd.DateOffset(days=5)))

p.fig.autofmt_xdate()
p.ax.set_xlabel('')
p.ax.set_ylabel('Casos COVID-19 - PB')
p.ax.set_title('Casos e Óbitos de COVID-19 na Paraíba')
p.fig.set_size_inches(8,4)

# ## Gráficos de dispersão em dados categóricos
#
# Quando há muitos valores repetidos em uma variável, os gráficos de dispersão podem não ilustrar efetivamente o comportamento dos dados. Neste caso, é interessante que o gráfico considere a repetição dos valores dentro de uma mesma categoria.

# Comentários:
#
# - Isto acontece quando o eixo horizontal contém variáveis categóricas e, assim, tem-se repetição de valores dentro de uma mesma categoria.

# Para gráficos deste tipo, utilizaremos os dados de óbitos por COVID-19 no Brasil. Agruparemos o número de óbitos por dia da semana.

# In[17]:

covid_BR_obitos = covid_BR.query('regiao == "Brasil"')[['obitosNovos','data']]

covid_BR_obitos.data = pd.to_datetime(covid_BR_obitos.data)

covid_BR_obitos['Dia'] = covid_BR_obitos.data.dt.weekday.map(
    {0:'Segunda-Feira',
     1:'Terça-Feira',
     2:'Quarta-Feira',
     3:'Quinta-Feira',
     4:'Sexta-Feira',
     5:'Sábado',
     6:'Domingo'})

covid_BR_obitos = covid_BR_obitos.set_index('data')
covid_BR_obitos

# Se quisermos determinar a ordem do eixo _x_, `relplot` não é a função ideal. Além disso, devido à sobreposição dos dados, ela definitivamente não é a ideal para variáveis categóricas. Vejamos:

# In[18]:

p = sns.relplot(x='Dia', y='obitosNovos', data=covid_BR_obitos)
p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# ## O gráfico *stripplot*
#
# O *stripplot* é um gráfico de dispersão onde a cada observação é colocado um deslocamento aleatório para evitar a sobreposição e fornecer uma ideia mais precisa da quantidade de dados.
#
# Vamos construir o *stripplot* através da função `catplot`. O *stripplot* é o gráfico padrão do `catplot` (tem o argumento `kind = 'strip'`).
#
# Podemos determinar a ordem das variáveis categóricas com o argumento *order*.

# In[19]:

p = sns.catplot(x='Dia', y='obitosNovos',
                data=covid_BR_obitos, order =
                ['Segunda-Feira', 'Terça-Feira',
                 'Quarta-Feira', 'Quinta-Feira',
                 'Sexta-Feira', 'Sábado', 'Domingo'])

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Se colocarmos `jitter=False`, obteremos o gráfico de dispersão usual (com o detalhe de que podemos definir a ordem dos rótulos do eixo *x*).

# In[20]:

p = sns.catplot(x='Dia', y='obitosNovos',
                jitter = False,
                data=covid_BR_obitos,
                order = ['Segunda-Feira', 'Terça-Feira',
                         'Quarta-Feira', 'Quinta-Feira',
                         'Sexta-Feira', 'Sábado', 'Domingo'])

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# ## O gráfico *swarmplot*
#
# O *swarmplot* é um gráfico de dispersão onde, diferentemente do *stripplot*, nenhum dado pode ficar sobreposto. Desta forma, também fornece uma ideia mais precisa da quantidade de dados.
#
# Construiremos o *swarmplot* através da função `catplot` com o argumento `kind = 'swarm'`. Como o *swarmplot* também é um tipo do `catplot`, podemos determinar a ordem das variáveis categóricas com o argumento `order`.

# In[21]:

p = sns.catplot(x='Dia', y='obitosNovos',
                kind = 'swarm',
                data=covid_BR_obitos,
                order = ['Segunda-Feira', 'Terça-Feira',
                         'Quarta-Feira', 'Quinta-Feira',
                         'Sexta-Feira', 'Sábado', 'Domingo'])

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# ## Gráficos de Barras e Colunas
#
# Para criar gráficos de barras e colunas com o *seaborn* utilizaremos a função `catplot` com o argumento `kind=bar`. Se a variável categórica estiver no eixo *x*, o gráfico será de coluna; se a variável categórica estiver no eixo *y*, o gráfico será de barra.

# In[22]:

covid_Regioes = covid_BR[['regiao','obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')/2

p = sns.catplot(x='regiao', y='obitosNovos',
                kind = 'bar',data=covid_Regioes.reset_index())

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# In[23]:

covid_Regioes = covid_BR[['regiao','obitosNovos']].groupby('regiao').sum().query('regiao != "Brasil"')/2

p = sns.catplot(x='obitosNovos', y='regiao',
                kind = 'bar',data=covid_Regioes.reset_index())

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# In[24]:

df_dict_series_sns = pd.DataFrame(df_dict_series.Idade).rename({'Idade':'Valor'}, axis=1)
df_dict_series_sns['Dado'] = 'Idade'

df_dict_series_sns_temp = pd.DataFrame(df_dict_series.Altura).rename({'Altura':'Valor'}, axis=1)
df_dict_series_sns_temp['Dado'] = 'Altura'
df_dict_series_sns = pd.concat([df_dict_series_sns, df_dict_series_sns_temp])

df_dict_series_sns_temp = pd.DataFrame(df_dict_series.Peso).rename({'Peso':'Valor'}, axis=1)
df_dict_series_sns_temp['Dado'] = 'Peso'
df_dict_series_sns = pd.concat([df_dict_series_sns, df_dict_series_sns_temp])

df_dict_series_sns

# In[25]:

p = sns.catplot(x='index', y='Valor',
                hue='Dado',
                data = df_dict_series_sns.reset_index(),
                kind='bar')

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# ## _Box Plot_ e plots alternativos
#
# Tanto o *BoxPlot* quanto os plots alternativos que apresentaremos aqui (*violinplot* e *boxenplot*) fazem parte do `catplot`. Para construir um
#
# - *Box Plot* utiliza-se o argumento `kind='box'`;
# - *Violin Plot* utiliza-se o argumento `kind='violin'`;
# - *Boxen Plot* (ou *letter-value plot*) utiliza-se o argumento `kind='boxen'`.
#
# ```{note}
# O *boxenplot* foi criado por Hadley Wickham (criador do *ggplot2* e da maioria dos pacotes do *tidyverse* do *R*) e colaboradores e é uma generalização do *BoxPlot* que apresenta mais quantis. Foi introduzido como [letter-value plots](https://vita.had.co.nz/papers/letter-value-plot.html). O *violinplot* recebe este nome, pois seu gráfico assemelha-se a um violino.
# ```

# In[26]:

p = sns.catplot(x='Dia', y='obitosNovos',
                kind = 'box',
                data=covid_BR_obitos,
                order = ['Segunda-Feira', 'Terça-Feira',
                         'Quarta-Feira', 'Quinta-Feira',
                         'Sexta-Feira', 'Sábado', 'Domingo'])

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# In[27]:

covid_regioes_diarios_px = covid_BR.set_index(
    'data').query('regiao != "Brasil"')[['obitosNovos', 'regiao']].reset_index().rename(
    {'obitosNovos':'Óbitos','regiao':'Região','data':'Data'},axis=1)

covid_regioes_diarios_px = covid_regioes_diarios_px.groupby(['Região','Data']).sum()/2
covid_regioes_diarios_px = covid_regioes_diarios_px.reset_index().set_index('Data')

covid_regioes_diarios_px

# In[28]:

p = sns.catplot(x='Região', y='Óbitos',
                kind = 'box',
                data=covid_regioes_diarios_px)

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Na presença de muitos *outliers*, como é o caso do gráfico anterior, é interessante considerar uma alternativa ao *Box Plot*.
#
# Vamos ver agora o *Boxen Plot* (ou *letter-value plots*). Este plot considera os quantis: ..., 0.8%, 1.56%, 3.13%, 6.25%, 12.5%, 25%, 50%, 75%, 87.5%, 93.75%, 96.88%, 98.44%, 99.24%, ...

# In[29]:

p = sns.catplot(x='Região', y='Óbitos',
                kind = 'boxen',
                data=covid_regioes_diarios_px)

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Porém, em um gráfico sem muitos *outliers*, o *Boxen Plot* não difere muito do *Box Plot*.

# In[30]:

p = sns.catplot(x='Dia', y='obitosNovos',
                kind = 'boxen',
                data=covid_BR_obitos,
                order = ['Segunda-Feira', 'Terça-Feira',
                         'Quarta-Feira', 'Quinta-Feira',
                         'Sexta-Feira', 'Sábado', 'Domingo'])
p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Na presença de muitos *outliers*, também é preferível um *Violin Plot* em vez de um *Box Plot*, para tornar visível o que está ocorrendo.

# In[31]:

p = sns.catplot(x='Região', y='Óbitos',
                kind = 'violin',
                data=covid_regioes_diarios_px)

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# Muitas vezes, é interessante sobrepor um *Violin Plot* a um *Swarm Plot* para evidenciar o comportamento da distribuição dos dados.

# In[32]:

p = sns.catplot(x='Região', y='Óbitos',
                kind = 'violin',
                data=covid_regioes_diarios_px)

sns.swarmplot(x='Região', y='Óbitos',
              data=covid_regioes_diarios_px,
              ax = p.ax,
              size=4, color='k')

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# In[33]:

p = sns.catplot(x='Dia', y='obitosNovos',
                kind = 'violin',
                data=covid_BR_obitos)

sns.swarmplot(x='Dia', y='obitosNovos',
              data=covid_BR_obitos,
              ax = p.ax, size=4, color='k')

p.ax.set_xlabel('');
p.fig.set_size_inches(8,4)

# ## Histogramas
#
# O *seaborn* constrói histogramas a partir da função `histplot`, ou da função obsoleta `distplot`.
#
# Incluímos um estimador de densidade baseado em núcleo Gaussiano (_Gaussian kernel_) utilizando o argumento `kde=True`.

# In[34]:

fig, ax = plt.subplots(figsize=(8,4))
_ = sns.histplot(covid_regioes_diarios_px.query('Região=="Nordeste"')['Óbitos'],kde=True)

# Para remover o estimador, selecionamos `kde=False`.

# In[35]:

fig, ax = plt.subplots(figsize=(8,4))
_ = sns.histplot(covid_regioes_diarios_px.query('Região=="Nordeste"')['Óbitos'],kde=False)

# Para plotarmos apenas o estimador de densidade sem o histograma, usamos `distplot` com a opção `hist=False`.

# In[36]:

fig, ax = plt.subplots(figsize=(8,4))
_ = sns.distplot(covid_regioes_diarios_px.query('Região=="Nordeste"')['Óbitos'],hist=False)

# É possível plotar o histograma com o estimador para qualquer série do _DataFrame_.

# In[37]:

fig, ax = plt.subplots(figsize=(8,4))
_ = sns.histplot(df_exemplo['coluna_1'],kde=True)

# ## Distribuição conjunta e marginal
#
# O histograma permite que verifiquemos a distribuição de uma ou mais variáveis, mas sem levar outras em consideração. Para plotarmos uma distribuição conjunta, bem como a distribuição individual (marginal) de cada variável, podemos utilizar a função `jointplot`.

# In[38]:

_ = sns.jointplot(x = 'coluna_1', y = 'coluna_2', data=df_exemplo, height=7)

# O próximo exemplo usa a função `jointplot` para plotar distribuições conjuntas relativas ao número de óbitos por Covid-19 por região do Brasil durante uma certa janela temporal.

# In[39]:

covid_regioes_diarios = pd.DataFrame()

regioes = covid_BR.query('regiao != "Brasil"')['regiao'].drop_duplicates().array

for regiao in regioes:
    temp_series = covid_BR.set_index('data').query('regiao == @regiao')['obitosNovos'].groupby('data').sum()/2
    temp_series.name = 'obitos_' + regiao
    covid_regioes_diarios = pd.concat([covid_regioes_diarios, temp_series], axis=1)

covid_regioes_diarios.index = pd.to_datetime(covid_regioes_diarios.index)
covid_regioes_diarios.head()

# In[40]:

_ = sns.jointplot(x='obitos_Nordeste', y='obitos_Sudeste',
                  data = covid_regioes_diarios, height=7)

# ## Estilos e cores
#
# O *seaborn* disponibiliza 5 estilos pré-definidos: *darkgrid*, *whitegrid*, *dark*, *white* e *ticks*. Vejamos cada um deles.

# In[41]:

import matplotlib.dates as mdates
from matplotlib.ticker import FuncFormatter

# In[42]:

sns.set_style("darkgrid")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[43]:

sns.set_style("whitegrid")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[44]:

sns.set_style("dark")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[45]:

sns.set_style("white")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[46]:

sns.set_style("ticks") # A diferença com o anterior são os "ticks" no eixo x
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# ### Molduras
#
# Utilizamos a função `despine` para adicionar ou remover molduras em plotagens com o *seaborn*. Podemos especificar lados para adicionar e remover molduras utilizando os booleanos `True` e `False`.

# In[47]:

sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7))
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21))
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y'))
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)
sns.despine(right=False, top=False)

# Podemos criar um tipo de "acolchoamento" aumentando a distância entre o gráfico e a moldura utilizando `offset`. Atribuindo um valor para este argumento, as bordas serão afastadas naturalmente. Um tipo de "corte estético" pode ser adicionado à moldura com `trim=False`.

# In[48]:

sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos',
                hue = 'Tipo',
                data=covid_PB_obitos_df.reset_index(),
                kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)
sns.despine(right=False, top=False, offset=30)

# In[49]:

sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos',
                hue = 'Tipo',
                data=covid_PB_obitos_df.reset_index(),
                kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)
sns.despine(offset=30, trim=True)

# ### Contextos e escala
#
# O *seaborn* possui contextos pré-definidos que mudam a escala do gráfico para melhor satisfazer a aplicação de interesse. Para definir o contexto, utilizamos a função `set_context`. Há 4 contextos pré-definidos: *paper*, *notebook*, *talk* e *poster*.

# In[50]:

sns.set_context("poster")
sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos',
                hue = 'Tipo',
                data=covid_PB_obitos_df.reset_index(),
                kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[51]:

sns.set_context("talk")
sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[52]:

sns.set_context("notebook")
sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[53]:

sns.set_context("paper")
sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos', hue = 'Tipo', data=covid_PB_obitos_df.reset_index(), kind='line')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# ### Paletas e mapas de cores
#
# É possível personalizar a paleta de cores a ser utilizada ou escolher uma da lista (extremamente extensa) de paletas disponíveis utilizando a função `set_palette`. Duas formas usuais de selecionar a paleta de cores são:
#
# - no escopo de uma instrução `with` por meio da função `color_palette`;
# - pelo argumento `palette` nas funções de construção gráfica.
#
# A função `color_palette()` aceita nomes de uma paleta do _seaborn_ (_deep_, _muted_, _bright_, _pastel_,_dark_,_colorbind_), um mapa de cores (_colormap_) do _matplotlib_, uma sequência de cores em qualquer formato aceitável pelo _matplotlib_, entre outras opções.
#
# ```{note}
# Para uma lista ampla de paletas, veja a discussão neste [post](https://medium.com/@morganjonesartist/color-guide-to-seaborn-palettes-da849406d44f) ou a [_Colormap reference_](https://matplotlib.org/stable/gallery/color/colormap_reference.html) do _matplotlib_.
# ```

# Abaixo temos alguns exemplos de paletas nativas do _seaborn_

# In[54]:

sns.color_palette()

# In[55]:

sns.color_palette('colorblind')

# In[56]:

sns.color_palette('bright')

# e de mapas do cores do _matplotlib_.

# In[57]:

sns.color_palette('Greens')

# In[58]:

sns.color_palette('turbo')

# In[59]:

sns.color_palette('cividis')

# Nos exemplos a seguir, plotamos alguns gráficos novamente com paletas diferentes.

# In[60]:

# paleta: 'BuPu'
sns.set_context("paper")
sns.set_style("ticks")
p = sns.relplot(x = 'data', y='Óbitos',
                hue = 'Tipo',
                data=covid_PB_obitos_df.reset_index(), kind='line',
                palette = 'BuPu')
p.fig.autofmt_xdate()
p.ax.xaxis.set_minor_locator(mdates.DayLocator(interval=7)) #Intervalo entre os tracinhos
p.ax.xaxis.set_major_locator(mdates.DayLocator(interval=21)) #Intervalo entre as datas
p.ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) #Formato da data
p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[61]:

# paleta: 'mako_r'
with sns.color_palette('mako_r'):
    p = sns.catplot(x='Região', y='Óbitos',
                    kind = 'violin',
                    data=covid_regioes_diarios_px)
    p.ax.set_xlabel(''); p.fig.set_size_inches(12,4)

# In[62]:

# paleta: icefire_r
sns.set_palette('icefire_r')
_ = sns.jointplot(x='obitos_Nordeste', y='obitos_Sudeste',
                  data = covid_regioes_diarios,
                  height=6)

# ## Nota
#
# Este capítulo baseia-se nas notas de aula da Profa. Andrea Rocha (CI/UFPB), elaboradas para o mini-curso [FMECD](https://gcpeixoto.github.io/FMECD/ipynb/01a-introducao.html).


#!/usr/bin/env python
# coding: utf-8

# # NAM 2019 pMuTT Workshop
#
# Instructions and materials for the "Theory, Applications, and Tools for Kinetic Modeling" workshop can be found on [our documentation page](https://vlachosgroup.github.io/pMuTT/nam_2019.html).
#

# # Table of Contents
#
# | **1\. [Virtual Kinetic Laboratory Ecosystem](#section_1)**
#
# | **2\. [Useful Links](#section_2)**
#
# | **3\. [Constants](#section_3)**
#
# |-- **3.1. [Access common constants in appropriate units](#section_3_1)**
#
# |-- **3.2. [Convert between units](#section_3_2)**
#
# |-- **3.3. [Convert between equivalent quantities](#section_3_3)**
#
# | **4\. [Exercise 1](#section_4)**
#
# | **5\. [Creating statistical mechanical objects using StatMech](#section_5)**
#
# |-- **5.1. [Supported StatMech models](#section_5_1)**
#
# |--|-- **5.1.1 [Translations](#section_5_1_1)**
#
# |--|-- **5.1.2. [Vibrations](#section_5_1_2)**
#
# |--|-- **5.1.3. [Rotations](#section_5_1_3)**
#
# |--|-- **5.1.4. [Electronic](#section_5_1_4)**
#
# |--|-- **5.1.5. [Miscellaneous](#section_5_1_5)**
#
# |-- **5.2. [Initializing StatMech modes individually](#section_5_2)**
#
# |-- **5.3. [Initializing StatMech modes using presets](#section_5_3)**
#
# | **6\. [Plot Thermodynamic Quantities](#section_6)**
#
# | **7\. [Exercise 2](#section_7)**
#
# | **8\. [Creating empirical objects](#section_8)**
#
# |-- **8.1. [Inputting a NASA polynomial directly](#section_8_1)**
#
# |-- **8.2. [Fitting an empirical object to a StatMech object](#section_8_2)**
#
# | **9\. [Input/Output](#section_9)**
#
# |-- **9.1. [Input via Excel](#section_9_1)**
#
# |-- **9.2. [Output via Thermdat](#section_9_2)**
#
# | **10\. [Reactions](#section_10)**
#
# | **11\. [Exercise 3](#section_11)**
#
# | **12\. [Solutions](#section_12)**
#
# |-- **12.1. [Solution 1](#section_12_1)**
#
# |-- **12.2. [Solution 2](#section_12_2)**
#
# |-- **12.3. [Solution 3](#section_12_3)**

#

# # 1. Virtual Kinetic Laboratory Ecosystem
#
#
#
#
#
#
# - Estimates thermochemical and kinetic parameters using statistical mechanics, transition state theory
# - Writes input files for kinetic models and eases thermodynamic analysis
# - Implemented in Python
#   - Easy to learn
#   - Heavily used in scientific community
#   - Object-oriented approach is a natural analogy to chemical phenomenon
# - Library approach allows users to define the starting point and end point
#
#
#

#

# # 2. Useful Links
#
# - [Documentation](https://vlachosgroup.github.io/pMuTT/): find the most updated documentation
# - [Issues](https://github.com/VlachosGroup/pmutt/issues): report bugs, request features, receive help
# - [Examples](https://vlachosgroup.github.io/pMuTT/examples.html): see examples

#

# # 3. Constants
#
# The [constants module](https://vlachosgroup.github.io/pMuTT/constants.html) has a wide variety of functions for constants and unit conversion.

#

# ## 3.1. Access common constants in appropriate units
# Below, we access Planck's constant in J s.

# In[1]:

from pmutt import constants as c

h1 = c.h('eV s', bar=True)
print('h = {} eV s'.format(h1))

#

# ## 3.2. Convert between units
# Below, we convert 12 atm of pressure to psi.

# In[2]:

from pmutt import constants as c

P_atm = 12. # atm
P_psi = c.convert_unit(num=P_atm, initial='atm', final='psi')

print('{} atm = {} psi'.format(P_atm, P_psi))

#

# ## 3.3. Convert between equivalent quantities
# Below, we convert 1000 wavenumbers (cm-1) to frequency.

# In[3]:

from pmutt import constants as c

wave_num = 1000. # cm-1
freq = c.wavenumber_to_freq(wave_num) # Hz

print('{} cm-1 = {} Hz'.format(wave_num, freq))

#

# # 4. Exercise 1
#
# Using `pmutt.constants`, calculate the dimensionless enthalpy (H/RT) using the following information:
# - H = 0.5 eV
# - T = 77 F

# In[4]:

# Fill in your answer for Exercise 1 here

#

# # 5. Creating statistical mechanical objects using StatMech
#
# Molecules show translational, vibrational, rotational, electronic, and nuclear modes.
#
#

#

# ## 5.1. Supported StatMech modes
#
#
#
# The StatMech object allows us to specify translational, vibrational, rotational, electronic and nuclear modes independently, which gives flexibility in what behavior you would like. Below are the available modes.

#

# ### 5.1.1. Translations
# - [``FreeTrans``](https://vlachosgroup.github.io/pMuTT/statmech.html#freetrans) - Translations assuming no intermolecular interactions

#

# ### 5.1.2. Vibrations
# - [``HarmonicVib``](https://vlachosgroup.github.io/pMuTT/statmech.html#harmonicvib) - Harmonic vibrations
# - [``QRRHOVib``](https://vlachosgroup.github.io/pMuTT/statmech.html#harmonicvib) - Quasi rigid rotor harmonic oscillator. Low frequency modes are treated as rigid rotations.
# - [``EinsteinVib``](https://vlachosgroup.github.io/pMuTT/statmech.html#einsteinvib) - Each atom in the crystal vibrates as independent 3D harmonic oscillators
# - [``DebyeVib``](https://vlachosgroup.github.io/pMuTT/statmech.html#debyevib) - Improves upon ``EinsteinVib`` by considering simultaneous vibrations. Improves accuracy at lower temperatures.

#

# ### 5.1.3. Rotations
# - [``RigidRotor``](https://vlachosgroup.github.io/pMuTT/statmech.html#rigidrotor) - Molecule can be rotated with no change in bond properties

#

# ### 5.1.4. Electronic
# - [``GroundStateElec``](https://vlachosgroup.github.io/pMuTT/statmech.html#groundstateelec) - Electronic ground state of the system
# - [``LSR``](https://vlachosgroup.github.io/pMuTT/statmech.html#linear-scaling-relationships-lsrs) - Linear Scaling Relationship to estimate binding energies using reference adsorbate

#

# ### 5.1.5. Miscellaneous
# - [``EmptyMode``](https://vlachosgroup.github.io/pMuTT/statmech.html#empty-mode) - Default mode if not specified. Does not contribute to any properties
# - [``ConstantMode``](https://vlachosgroup.github.io/pMuTT/statmech.html#constant-mode) - Specify arbitrary values to thermodynamic quantities
#
# Using a ``StatMech`` mode gives you access to all the common thermodynamic properties.
#
#
#
# For this example, we will use a hydrogen molecule as an ideal gas:
# - translations with no interaction between molecules
# - harmonic vibrations
# - rigid rotor rotations
# - ground state electronic structure
# - no contribution from nuclear modes.
#
#

#

# ## 5.2. Initializing StatMech modes individually

# In[5]:

from ase.build import molecule
from pmutt.statmech import StatMech, trans, vib, rot, elec

H2_atoms = molecule('H2')

'''Translational'''
H2_trans = trans.FreeTrans(n_degrees=3, atoms=H2_atoms)

'''Vibrational'''
H2_vib = vib.HarmonicVib(vib_wavenumbers=[4342.]) # vib_wavenumbers in cm-1

'''Rotational'''
H2_rot = rot.RigidRotor(symmetrynumber=2, atoms=H2_atoms)

'''Electronic'''
H2_elec = elec.GroundStateElec(potentialenergy=-6.77,spin=0) # potentialenergy in eV

'''StatMech Initialization'''
H2_statmech = StatMech(name='H2',
                       trans_model=H2_trans,
                       vib_model=H2_vib,
                       rot_model=H2_rot,
                       elec_model=H2_elec)

'''Calculate thermodynamic properties'''
H_statmech = H2_statmech.get_H(T=298., units='kJ/mol')
S_statmech = H2_statmech.get_S(T=298., units='J/mol/K')
print('H_H2(T=298 K) = {:.1f} kJ/mol'.format(H_statmech))
print('S_H2(T=298 K) = {:.2f} J/mol/K'.format(S_statmech))

#

# ## 5.3. Initializing StatMech modes using presets
#
# Commonly used models can be accessed via [``presets``](https://vlachosgroup.github.io/pMuTT/statmech.html#presets). The currently supported models are:
#
# - [``idealgas``](https://vlachosgroup.github.io/pMuTT/statmech.html#ideal-gas-idealgas) - Ideal gases
# - [``harmonic``](https://vlachosgroup.github.io/pMuTT/statmech.html#harmonic-approximation-harmonic) - Typical for surface species
# - [``electronic``](https://vlachosgroup.github.io/pMuTT/statmech.html#electronic-electronic) - Only has electronic modes
# - [``placeholder``](https://vlachosgroup.github.io/pMuTT/statmech.html#placeholder-placeholder) - No contribution to any property
# - [``constant``](https://vlachosgroup.github.io/pMuTT/statmech.html#constant-constant) - Use arbitrary constants to thermodynamic properties
#

# In[6]:

from ase.build import molecule
from pmutt.statmech import StatMech, presets

H2_statmech = StatMech(atoms=molecule('H2'),
                       vib_wavenumbers=[4342.], # cm-1
                       symmetrynumber=2,
                       potentialenergy=-6.77, # eV
                       spin=0.,
                       **presets['idealgas'])

'''Calculate thermodynamic properties'''
H_statmech = H2_statmech.get_H(T=298., units='kJ/mol')
S_statmech = H2_statmech.get_S(T=298., units='J/mol/K')
print('H_H2(T=298 K) = {:.1f} kJ/mol'.format(H_statmech))
print('S_H2(T=298 K) = {:.2f} J/mol/K'.format(S_statmech))

#

# # 6. Plot Thermodynamic Quantities
# Use [`pmutt.plot_1D`](https://vlachosgroup.github.io/pMuTT/visual.html#plot-1d) and [`pmutt.plot_2D`](https://vlachosgroup.github.io/pMuTT/visual.html#plot-2d) to plot any function with respect to 1 or 2 variables.

# In[7]:

import numpy as np
from matplotlib import pyplot as plt
from pmutt import plot_1D, plot_2D

T = np.linspace(300., 500.)

f1, ax1 = plot_1D(H2_statmech,
                  x_name='T', x_values=T,
                  methods=('get_H', 'get_S', 'get_G'),
                  get_H_kwargs={'units': 'kcal/mol'},
                  get_S_kwargs={'units': 'cal/mol/K'},
                  get_G_kwargs={'units': 'kcal/mol'})
f1.set_size_inches(6, 6)
f1.set_dpi(200)
plt.show()

#

# # 7. Exercise 2
#
# 1. Create a ``StatMech`` object for ideal gas-phase H2O. The necessary inputs are given below.
#
# |            Parameter           |             Value            |
# |--------------------------------|------------------------------|
# |              atoms             |       `molecule('H2O')`      |
# |      Potential Energy (eV)     |            -6.7598           |
# |         Symmetry number        |               2              |
# |              Spin              |               0              |
# | Vibrational Wavenumbers (cm-1) | 3825.434, 3710.264, 1582.432 |
#
# 2. Calculate the Gibbs energy in eV for H2O at T = 500 K and P = 2 bar.
#
# 3. Create a ``StatMech`` object for a Cu crystal using the ``DebyeVib`` model for the vibration mode and ``GroundStateElec`` model for electronic mode. The necessary inputs are given below.
#
# | Parameter              | Value      |
# |------------------------|------------|
# | Debye Temperature (K)  | 310        |
# | Interaction energy (eV)| 0          |
# | Potential energy (eV)  | -14.922356 |
#
# 4. Plot the H (in eV) and S (in eV/K) for Cu between T = 300 - 700 K.

# In[8]:

# Fill in your answer for Exercise 2 here

# 1.

# 2.

# 3.

# 4.

#

# # 8. Creating empirical objects
# Currently, pMuTT supports [NASA polynomials](https://vlachosgroup.github.io/pMuTT/empirical.html#nasa) and [Shomate polynomials](https://vlachosgroup.github.io/pMuTT/empirical.html#shomate). They can be initialized in three ways:
# - passing in the polynomials directly
# - from a model (e.g. ``StatMech``, ``Shomate``) (``from_model``)
# - from heat capacity, enthalpy and entropy data (``from_data``)
#
#

#

# ## 8.1. Inputting a NASA polynomial directly
#
# The H2 NASA polynomial from the [Burcat database](http://combustion.berkeley.edu/gri_mech/version30/files30/thermo30.dat) is represented as:
#
# ```
# H2                TPIS78H   2               G   200.000  3500.000  1000.000    1
#  3.33727920E+00-4.94024731E-05 4.99456778E-07-1.79566394E-10 2.00255376E-14    2
# -9.50158922E+02-3.20502331E+00 2.34433112E+00 7.98052075E-03-1.94781510E-05    3
#  2.01572094E-08-7.37611761E-12-9.17935173E+02 6.83010238E-01                   4
# ```
#
# This can be translated to pMuTT syntax using:

# In[9]:

from pmutt.empirical.nasa import Nasa

# Initialize NASA polynomial
H2_nasa = Nasa(name='H2',
               elements={'H': 2},
               phase='G',
               T_low=200., T_mid=1000., T_high=3500.,
               a_low=[2.34433112E+00, 7.98052075E-03, -1.94781510E-05,
                      2.01572094E-08, -7.37611761E-12, -9.17935173E+02,
                      6.83010238E-01],
               a_high=[3.33727920E+00, -4.94024731E-05, 4.99456778E-07,
                       -1.79566394E-10, 2.00255376E-14, -9.50158922E+02,
                       -3.20502331E+00])

# Calculate thermodynamic quantities using the same syntax as StatMech
H_H2 = H2_nasa.get_H(units='kcal/mol', T=298.)
print('H_H2(T=298 K) = {} kcal/mol'.format(H_H2))

# Show thermodynamic quantities vs. T
T = np.linspace(200., 3500.)
f2, ax2 = plot_1D(H2_nasa,
                  x_name='T', x_values=T,
                  methods=('get_H', 'get_S', 'get_G'),
                  get_H_kwargs={'units': 'kcal/mol'},
                  get_S_kwargs={'units': 'cal/mol/K'},
                  get_G_kwargs={'units': 'kcal/mol'})
f2.set_size_inches(6, 6)
f2.set_dpi(200)
plt.show()

#

# ## 8.2. Fitting an empirical object to a StatMech object
# Empirical objects can be made directly using ``StatMech`` objects and the ``from_model`` method.

# In[10]:

H2_nasa = Nasa.from_model(name='H2',
                          T_low=200.,
                          T_high=3500.,
                          model=H2_statmech)

# Compare the statistical mechanical model to the empirical model
f3, ax3 = H2_nasa.plot_statmech_and_empirical(Cp_units='J/mol/K',
                                              H_units='kJ/mol',
                                              S_units='J/mol/K',
                                              G_units='kJ/mol')
f3.set_size_inches(6, 8)
f3.set_dpi(200)
plt.show()

#

# # 9. Input/Output
# pMuTT has more IO functionality than below. See this page for [supported IO functions](https://vlachosgroup.github.io/pMuTT/io.html).

#

# ## 9.1. Input via Excel
#
# Encoding each object in Python can be tedious. You can read several species from Excel spreadsheets using [``pmutt.io.excel.read_excel``](https://vlachosgroup.github.io/pmutt/io.html?highlight=read_excel#pmutt.io.excel.read_excel). Note that this function returns a list of dictionaries. This output allows you to initialize whichever object you want using kwargs syntax. There are also [special rules that depend on the header name](https://vlachosgroup.github.io/pMuTT/io.html#special-rules).
#
# Below, we show an example importing species data from a spreadsheet and creating a series of NASA polynomials.

# In[11]:

import os
from pprint import pprint
from pathlib import Path
from pmutt.io.excel import read_excel
from pmutt.empirical.nasa import Nasa

# Find the location of Jupyter notebook
# Note that normally Python scripts have a __file__ variable but Jupyter notebook doesn't.
# Using pathlib can overcome this limiation
try:
    notebook_folder = os.path.dirname(__file__)
except NameError:
    notebook_folder = Path().resolve()
os.chdir(notebook_folder)

# Read the data from Excel
ab_initio_data = read_excel(io='./input/NH3_Input_Data.xlsx', sheet_name='species')
pprint(ab_initio_data)

# In[12]:

# Create NASA polynomials using **kwargs syntax
nasa_species = []
for species_data in ab_initio_data:
    single_nasa_species = Nasa.from_model(T_low=100.,
                                          T_high=1500.,
                                          **species_data)
    nasa_species.append(single_nasa_species)

# Print out a table using enthalpy, entropy, Gibbs energy at 298 K for each species
print('Name         Enthalpy (kcal/mol)   Entropy (cal/mol/K)   Gibbs energy (kcal/mol)')
print('--------------------------------------------------------------------------------')
for single_nasa_species in nasa_species:
    name = single_nasa_species.name
    H = single_nasa_species.get_H(units='kcal/mol', T=298.)
    S = single_nasa_species.get_S(units='cal/mol/K', T=298.)
    G = single_nasa_species.get_G(units='kcal/mol', T=298.)
    print('{:12}       {:10.1f}       {:15.1f}       {:15.1f}'.format(name, H, S, G))

#

# ## 9.2. Output via Thermdat
# The thermdat format uses NASA polynomials to represent several species. It has a very particular format so doing it manually is error-prone. You can write a list of ``Nasa`` objects to thermdat format using [``pmutt.io.thermdat.write_thermdat``](https://vlachosgroup.github.io/pmutt/io.html#pmutt.io.thermdat.write_thermdat).
#
# Below, we write a thermdat file using the species imported from the spreadsheet.

# In[13]:

from pmutt.io.thermdat import write_thermdat

write_thermdat(filename='./output/thermdat', nasa_species=nasa_species)

# Similarly, a list of ``Nasa`` objects can be read from a thermdat using [``pmutt.io.thermdat.read_thermdat``](https://vlachosgroup.github.io/pMuTT/io.html#pmutt.io.thermdat.read_thermdat).

# In[14]:

from pmutt.io.thermdat import read_thermdat

nasa_species = read_thermdat('./output/thermdat')

#

# # 10. Reactions
#
#
#
# ``Reaction`` objects can be created by putting together ``Nasa``, ``Shomate`` and ``StatMech`` objects.
#
#
#
#
# The ``from_string`` method is the easiest way to create a ``Reaction`` object. It requires the relevant species to be in a dictionary and a string to describe the reaction.
#
#
#
# We will demonstrate its use for the formation of NH3.

# In[15]:

from pmutt.empirical.nasa import Nasa
from pmutt.empirical.shomate import Shomate
from pmutt.reaction import Reaction

# Create species. Note that you can mix different types of species
species = {
    'H2': StatMech(name='H2', atoms=molecule('H2'),
                   vib_wavenumbers=[4342.], # cm-1
                   symmetrynumber=2,
                   potentialenergy=-6.77, # eV
                   spin=0.,
                   **presets['idealgas']),
    'N2': Nasa(name='N2', T_low=300., T_mid=643., T_high=1000.,
               a_low=[3.3956319945669633, 0.001115707689025668,
                      -4.301993779374381e-06, 6.8071424019295535e-09,
                      -3.2903312791047058e-12, -191001.55648623788,
                      3.556111439828502],
               a_high=[4.050329990684662, -0.0029677854067980108,
                       5.323485005316287e-06, -3.3518122405333548e-09,
                       7.58446718337381e-13, -191086.2004520406,
                       0.6858235504924011]),
    'NH3': Shomate(name='NH3', T_low=300., T_high=1000.,
                   a=[18.792357134351683, 44.82725349479501,
                      -10.05898449447048, 0.3711633831565547,
                      0.2969942466370908, -1791.225746924463,
                      203.9035662274934, 1784.714638346206]),
}

# Define the formation of water reaction
rxn = Reaction.from_string('1.5H2 + 0.5N2 = NH3', species)

# Calculate forward change in enthalpy
H_rxn_fwd = rxn.get_delta_H(units='kcal/mol', T=300.)
print('Delta H_fwd(T = 300 K) = {:.1f} kcal/mol'.format(H_rxn_fwd))

# Calculate reverse change in enthalpy
H_rxn_rev = rxn.get_delta_H(units='kcal/mol', T=300., rev=True)
print('Delta H_rev(T = 300 K) = {:.1f} kcal/mol'.format(H_rxn_rev))

# Calculate enthalpy of reactants
H_react = rxn.get_H_state(units='kcal/mol', T=300., state='reactants')
print('H_reactants(T = 300 K) = {:.1f} kcal/mol'.format(H_react))

#

# ## 11. Exercise 3
#
# 1. Use [``pmutt.io.thermdat.read_thermdat``](https://vlachosgroup.github.io/pMuTT/io.html#pmutt.io.thermdat.read_thermdat) to read the thermdat from './output/thermdat'.
#
# 2. Convert the list of ``Nasa`` to a dictionary of ``Nasa`` using ``pmutt.pmutt_list_to_dict``. The syntax to use the function is shown below.
#
# ```
# from pmutt import pmutt_list_to_dict
#
# species_dict = pmutt_list_to_dict(species_list)
# ```
#
# 3. Create a ``Reaction`` from the string: ``NH3(S) + RU(S) = TS1_NH3(S) = NH2(S) + H(S)`` and the dictionary from step 2.
#
# 4. Calculate the forward reaction enthalpy in kcal/mol at 298 K using [``Reaction.get_delta_H``](https://vlachosgroup.github.io/pMuTT/reactions.html#pmutt.reaction.Reaction.get_E_act).
#
# 5. Calculate the forward activation energy in kcal/mol at 298 K using [``Reaction.get_E_act``](https://vlachosgroup.github.io/pMuTT/reactions.html#pmutt.reaction.Reaction.get_E_act).

# In[16]:

# Fill in your answer for Exercise 3

# 1.

# 2.

# 3.

# 4.

# 5.

#

# # 12. Solutions

#

# ## 12.1. Solution to Exercise 1
# [Link to Exercise 1](#section_4)

# In[17]:

from pmutt import constants as c

# Define information given
H = 0.5 # eV
T = 77 # F

# Calculate H/RT
HoRT = H/c.R('eV/K')/c.convert_unit(77, initial='F', final='K')
print('H/RT = {}'.format(HoRT))

#

# ## 12.2. Solution to Exercise 2
# [Link to Exercise 2](#section_7)

# In[18]:

from ase.build import molecule
from pmutt import plot_1D
from pmutt.statmech import StatMech, presets
from pmutt.statmech.vib import DebyeVib
from pmutt.statmech.elec import GroundStateElec

# 1. Create H2O molecule
H2O_statmech = StatMech(atoms=molecule('H2O'),
                        potentialenergy=-6.7598,
                        symmetrynumber=2,
                        spin=0,
                        vib_wavenumbers=[3825.434, 3710.264, 1582.432],
                        **presets['idealgas'])

# 2. Calculate Gibbs energy of H2O at T = 500 K and P = 2 bar
T = 500. # K
P = 2. # bar
G_H2O = H2O_statmech.get_G(units='eV', T=T, P=P)
print('G_H2O(T = 500 K, P = 2 bar) = {} eV'.format(G_H2O))

# 3. Create Cu crystal
Cu_vib = DebyeVib(debye_temperature=310., interaction_energy=0.)
Cu_elec = GroundStateElec(potentialenergy=-14.922356)
Cu_statmech = StatMech(vib_model=Cu_vib, elec_model=Cu_elec)

# 4. Plot the 1D profile for H and S between 300 K and 700 K
T = np.linspace(300., 700.) # K
f2, ax2 = plot_1D(Cu_statmech,
                  x_name='T', x_values=T,
                  methods=('get_H', 'get_S'),
                  get_H_kwargs={'units': 'eV'},
                  get_S_kwargs={'units': 'eV/K'})
f2.set_size_inches(6, 6)
f2.set_dpi(200)
plt.show()

#

# ## 12.3. Solution to Exercise 3
# [Link to Exercise 3](#section_11)

# In[19]:

from pmutt.io.thermdat import read_thermdat
from pmutt import pmutt_list_to_dict
from pmutt.reaction import Reaction

# 1. Read the thermdat file
species_list = read_thermdat('./output/thermdat')

# 2. Convert the list of Nasa to a dictionary of Nasa
species_dict = pmutt_list_to_dict(species_list)

# 3. Create a Reaction from the specified string
rxn = Reaction.from_string('NH3(S) + RU(S) = TS1_NH3(S) = NH2(S) + H(S)', species_dict)

# 4. Calculate the reaction enthalpy
H_rxn = rxn.get_delta_H(units='kcal/mol', T=298.)
print('H_rxn = {:.1f} kcal/mol'.format(H_rxn))

# 5. Calculate the forward activation energy
Ea = rxn.get_E_act(units='kcal/mol', T=298.)
print('Ea_fwd = {:.1f} kcal/mol'.format(Ea))


# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""
"""-------------------------------------------------------------------------------------------------------------------------------------------------------------- """

"""
자료구조 : 1. sequence 자료구조 (순서있음)
          2. 딕셔너리, 세트 (순서없음)

인덱싱 : 리스트에서 하나의 요소를 인덱스 연산자를 통하여 참조(접근)하는 것

슬라이싱 : 리스트 안에서 범위를 지정하여서 원하는 요소들을 선택하는 연산

리스트 : 여러 개의 데이터가 저장되어 있는 자료구조
리스트가 필요한 이유 : 여러 개의 데이터가 저장되어 있는 자료구조
"""

# 문자열 인덱싱 & 슬라이싱

text = "IT Will is power."
print(text[:-2]) # IT Will is powe
print(text[:8], text[-1])

# 인덱싱
flist = ["apple", "banana", "tomato", "peach", "pear" ]
print(flist[0], flist[3], flist[-1])

# 슬라이싱
a = [0,1,4,9,16,25,36,49]
a[3:6]

# 리스트 (append로 추가해서 리스트를 만들어보는 것)

scores = [ ]
for i in range(10):
    scores.append(int(input("성적을 입력하시오:")))
print(scores)

scores[0] = 80

scores[i] = 10;
scores[i+2] = 20;

# 리스트의 요소갯수만큼 리스트가 반복되어 출력
for element in scores:
    print(scores)

# 복잡한 리스트
list1 = [12,"dog",180.14] # 혼합자료형
list2 = [["Seoul", 10], ["Paris", 12], ["London", 50]] # 내장 리스트

# 리스트 기초연산
marvel_heroes = [ "스파이더맨", "헐크", "아이언맨" ]
dc_heroes = [ "슈퍼맨", "배트맨", "원더우먼" ]

heros = marvel_heroes + dc_heroes
heros
# 리스트에 곱하기
values = [1,2,3]*3
values # [1, 2, 3, 1, 2, 3, 1, 2, 3]
len(values)

# 요소추가하기
developteam = []
developteam.append("이유현")
developteam.append("성민승")
developteam.append("김동완")

developteam

# 리스트 안의 내용 조회
if "이유현" in developteam:
    print("내부인원")

# 리스트 인덱스 확인
developteam.index("이유현") # 0
developteam.index("김동완") # 2

# 리스트 최소값 최대값
values = [ 100, 20, 31, 45, 15, 6, 7, 8, 9, 10 ]
min(values)
max(values)

# 리스트에서 sort 쓰기 정렬~~~
values.sort()
value2=sorted(values)
print(value2)

# 리스트 내의 조건문
list1 = [3,4,5]
list2 = [x*2 for x in list1]
print(list2)

# 2차원 리스트
s = [
[ 1, 2, 3, 4, 5 ] ,
[ 6, 7, 8, 9, 10 ],
[11, 12, 13, 14, 15 ]
]

print(s)

# 동적으로 2차원 리스트 생성

rows = 3
cols = 5

s = []
for row in range(rows):
    s += [[3]*cols]

print("s=",s) # s= [[3, 3, 3, 3, 3], [3, 3, 3, 3, 3], [3, 3, 3, 3, 3]]

rows = len(s)
cols = len(s[0])
cols
for r in range(rows):
    for c in range(cols):
        print(s[r][c], end=",")
    print()

"""
    tuple!!
    튜플은 변경될 수 없는 리스트 + 순서가 없다!!

    tuple('listname')
    : 리스트를 튜플로 변경한다.
"""
# tuple을 변경하려고 해보자

t1 = (1,2,3,4,5);
t2 = (1,2,3,4,5);

t1[0] =100; # TypeError: 'tuple' object does not support item assignment

# 튜플 대입 연산
student1 = ("철수",19,"CS")
(name,age,major) = student1
name # '철수'

"""
    set!!
    세트는 중복되지 않은 항목들이 모인것 + 순서가 없다!!

"""

numbers = {1,2,2,3,3,3,4}

numbers # {1, 2, 3, 4}

# 요소 추가
numbers.add(5)

"""

    dictionary
    딕셔너리는 키(key)와 값(value)의 쌍을 저장할 수 있는 객체

"""

# 형태
dictionary = {'name':'이유현','phone':'01091597160','score':100}
dictionary['score']
# 추가하기

dictionary['speed'] = '1000'
print(dictionary)

# 항목 순회하며 출력하기.

for item in dictionary.items():
    print(item)
"""
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
    plot 문제로 정리하기
    1. matplotlib
        1) 한글 및 음수 부호 지원
        2) 기본차트 시각화 - 기본 선 스타일과 색상, x축 y축 스타일&색상, color와 marker 이용
        3) 산점도, 히스토그램, 상자그래프
        3) 이산형 변수 시각화 - 가로막대 그래프, 세로막대 차트, 원차트
        4) subplot 차트
        5) 시계열차트
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
"""

data3= np.random.randn(50) # 난수
data4= np.random.randn(50).cumsum() # 난수

chart.plot(data3, color='r', label='step',
drawstyle="steps-post")

chart.plot(data4, color='g', label='line')
plt.legend(loc='best')
plt.ylabel('y label')
plt.xlabel('x label')
plt.title('chart title')
plt.show()

import matplotlib.pyplot as plt
import seaborn as sn

# 문3) seaborn의  titanic 데이터셋을 이용하여 다음과 같이 단계별로 시각화하시오.
titanic = sn.load_dataset('titanic')
print(titanic.info())

#  <단계1> 'total_bill','tip','sex','size' 칼럼으로 서브셋 만들기
titanic_df = titanic[['survived','pclass', 'age','fare']]
print(titanic_df.info())
#sn.pairplot(data=DataFrame, hue='집단변수', kind='scatter')

# <단계2> 성별(sex) 칼럼을 집단변수로 산점도행렬 시각화
sn.pairplot(data=titanic_df, hue='survived')
plt.show()

# <단계3> 산점도행렬의 시각화 결과 해설하기
'''
pclass : 3등석 일수록 사망비율 매우 높음
pclass vs fare : 1등석 일수록 고 요금
age : 25~50세 사이에서 가장 높은 빈도, 사망과 생존 비율 비슷
age vs fare : 대체적으로 나이가 많고, 요금이 낮은 경우 사망 비율 높음
fare : 비용이 저렴한 경우가 상대적으로 많은 분포
fare vs age : 대체적으로 요금이 낮고, 나이가 50대 이상인 경우 사망 비율 높음
'''

# survived vs age
# 연령대 생존비율 : 20~40
titanic[titanic['survived'] == 1].age.plot(kind = 'hist', color = 'blue')
# 연령대 사망비율 : 20~40
titanic[titanic['survived'] == 0].age.plot(kind = 'hist', color = 'green')

# 문4) seaborn의 tips 데이터셋을 이용하여 다음과 같이 단계별로 시각화하시오.
tips = sn.load_dataset('tips')
print(tips.info())

# <단계1> 'total_bill','tip','sex','size' 칼럼으로 서브셋 만들기
tips_df = tips[['total_bill','tip','sex','size']]

# <단계2> 성별(sex) 칼럼을 집단변수로 산점도행렬 시각화
sn.pairplot(data=tips_df, hue='sex')
plt.show()

# <단계3> 산점도행렬의 시각화 결과 해설하기
"""
total_bill : 총금액 15~20 사이가 가장 높은 빈도, 금액이 클 수록 남자 지불
total_bill vs tip  : 대체적으로 비례관계, 총금액과 팁이 많은 경우 남자 지불
tip : 팁은 1~5 사이가 가장 높은 빈도, 팁 금액이 클 수록 남자 지불
total_bill vs size : 행사규모가 작은 경우 여성 지불
size : 행사규모 2가 가장 높은 빈도, 특히 4일때 남자 지불
size vs total_bill : 대체적으로 비례관계, 규모가 큰 경우 총금액이 많음

"""
import pandas as pd # object
import numpy as np # dataset
import matplotlib.pyplot as plt # plt.show()

# 1. 기본 차트 시각화
ser = pd.Series(np.random.randn(10)) # 1d
print(ser)

# 1차원 객체 : 기본차트 - 선 그래프
ser.plot(color='g')
plt.show()

# 2차원 객체
df = pd.DataFrame(np.random.randn(10, 4),
                  columns=('one','two','three','fore'))

print(df)

# 기본차트 : 선 그래프
df.plot()
plt.show()

# 막대차트 : 세로
df.plot(kind='bar', title = 'bar chart')
plt.show()

# 막대차트 : 가로
df.plot(kind='barh', title = 'bar chart')
plt.show()

# 막대차트 : 가로, 누적형
df.plot(kind='barh', title = 'barh chart', stacked=True)
plt.show()

# 2. dataset 이용
import os

os.chdir('C:/ITWILL/4_Python-II/data')
tips = pd.read_csv('tips.csv')
print(tips.info())

# 교차분할표 : 집단변수 이용
# 요일(day):행 vs 규모(size):열
tips['day'].unique() # ['Sun', 'Sat', 'Thur', 'Fri']
tips['size'].unique()# [2, 3, 4, 1, 6, 5]

tab = pd.crosstab(index=tips['day'], columns=tips['size'])
print(tab)

# 테이블 정보
tab.shape # (4, 6)
tab.index # 행 이름
tab.columns # 열 이름

#tab.index = 수정 이름
type(tab) # pandas.core.frame.DataFrame

help(tab.plot)

# size : 1, 6 제외 -> subset
#obj.loc[행, 열]
new_tab = tab.loc[:, 2:5]
print(new_tab)

new_tab.plot(kind='barh', stacked=True,
         title = 'day and size')
plt.show()

"""
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
plot 예제 끝~~
"""

"""
---------------------------------------------------------------------------------------------------------------------------------------------------------------------

1. Group by : 머 대강 칼럼들을 특정 변수의 조건에 맞게 그룹화 시키는거다
2. apply :
3. Pivot table ---> df.pivot(index='x',columns='y',values='z')
        - 좌측 index(행)를 어떤 칼럼으로 설정할지
        - 칼럼(열)쪽을 y칼럼으로 세우고
        - 안에 채울 values 값 z로 설정

---------------------------------------------------------------------------------------------------------------------------------------------------------------------
"""

"""

NUMPY!!!!!!!!!!!!!
    1. 배열 생성 array()
    - arange() : 배열 객체 반환
    - linspace() : 시작점과 끝점을 균일 간격으로 나눈 점들을 생성
    - reshape() : 행수와 열수를 조절
    2. 특수 행렬 생성 zeros() : 0으로 채워진 배열, ones() : 1로 채워진 배열 ,eye() : 항등행렬

    3. 난수 생성  numpy.random.normal(size = 개수)
    4. 산술연산

"""

"""
# Series Pandas의 Series는 1차원 데이터를 다루는 데 효과적인 자료구조
values 속성을 호출하면 데이터의 배열 원소가 리턴
index 속성을 호출하면 인덱스의 정보가 리턴
각각의 데이터는 [인덱스]를 이용해서 접근이 가능
numpy 함수 사용 가능
dict 객체로 생성 가능
"""
# code 1

from pandas import Series, DataFrame
import numpy as np
import pandas as pd

price = Series([4000, 3000, 3500, 2000])
print(price)
print(price.index)
print(price.values)
print('====================')
fruit = Series([4000, 3000, 3500, 2000],
index=['apple', 'mellon','orange', 'kiwi'])
print(fruit)
print(fruit[0]) # 순번 이용 데이터 접근
print(fruit['apple']) # 인덱스 이용 데이터 접근
print(fruit[fruit>3000]) # 부울리언 식
print("=================")

# code 2
from pandas import Series, DataFrame
import numpy as np
import pandas as pd

good1 = Series([4000,3500,None,2000],index = ['apple','mango','orange','kiwi'])

good2 = Series([3000,3000,3500,2000],index = ['apple','mango','orange','kiwi'])

print(pd.isnull(good1)) # NaN값 검출 none이면 True를 반환
print (good1+good2)

# DataFrame

"""
# DataFrame은 행과 열로 구성된 2차원 데이터를 다루는 데 효과적인 자료구조
일반적으로 딕셔너리 활용해서 생성
입력가능한 데이터
1. 2차원 ndarray
2. 리스트, 튜플,dict, Series의 dict
3. dict, Series의 list
4. 리스트, 튜플의 리스트
5. 칼럼 뽑는 방법
    1) data.iloc[[행]],[열]  # 행은 index

"""
# code 1
from pandas import Series, DataFrame

items = {'code': [1,2,3,4,5,6],
'name': ['apple','watermelon','oriental melon', 'banana', 'lemon', 'mango'],
'manufacture': ['korea', 'korea', 'korea','philippines','korea', 'taiwan'],
'price':[1500, 15000,1000,500,1500,700]}

data = DataFrame(items)
print(data)

# 특정 컬럼만 뽑기
data1 = DataFrame(items, columns = ['code', 'price'])
print(data1)
print(data.loc[0]) # 0 행 출력 가로로 나옴
print(data.loc[:0]) # 0 행 출력 세로로 나옴
print(data.loc[[2],['name']])

# 데이터 프레임 변경해보기
data.index = np.arange(1,7,1) # 1~6까지 인덱스 설정
data.columns
data = data.reindex(['1','2','3','4','5','7'],columns = ['code', 'name', 'manufacture', 'price'])
print(data.index)
print(data);

"""-------------------------------------------------------------------------------------------------------------------------------------------------------------- """
# 정규분포 생성 알고리즘
""" 정규분포란? 가우시안 정규 분포 :
    자연 현상에서 나타나는 숫자를 확률 모형으로 모형화할 때 가장 많이 사용되는 모형
    표준편차 1배안에 전체 데이터의 약 70% 이상이 몰려있고
    1.96배 안에 95% 이상이 분포된 경우
    """
from pandas import Series, DataFrame
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from scipy import stats
import scipy as sp
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
mu = 0
std = 1
rv = sp.stats.norm(mu, std)
xx = np.linspace(-5, 5, 100)
plt.plot(xx, rv.pdf(xx))
plt.ylabel("확률")
plt.title("정규분포곡선")
plt.show()
x = rv.rvs(100) # rvs 메서드로 시뮬레이션해 샘플을 얻는것

print(x)

# 검정통계 , 유의확률(p-value)
"""
    검정(testing)은  데이터  뒤에  숨어있는  확률  변수의  분포와  모수에  대한  가설의  진 위를  정량적(quantitatively)으로  증명하는  작업

    실제 모집단에서 표본 몇 십 개 또는 몇 백 개를 추출해서 그것의 분산(표본분산)이나 평균(표본평균)을 사용해야 하는 경우가 대 부분입니다.
   표본수가  크지  않을  때  표본분산(표본표준편차)을  사용한  테스트는  t-분포를  이용 한다고  해서  T-test라고  합니다.
   가설  증명  즉  검정의  기본적인  논리는  다음과  같습니다.
   만약  가설이  맞다면  즉, 모수  값이  특정한  조건을  만족한다면  해당  확률  변수로부터  만 들어진  표본(sample) 데이터들은  어떤  규칙을  따르게  된다.
    해당 규칙에 따라 표본 데이터 집합에서 어떤 숫자를 계산하면 계산된 숫자는 특정한 확률 분포를 따르게 된다. 이 숫자를 검정 통계치(test statistics)라고 하며 확률 분포를 검정 통계 분포(test statistics distribution)라고 한다. 검정 통계 분포의 종류 및 모수의 값은 처음에 정한 가설에 의해 결정된다. 이렇게 검정 통계 분포를 결정하는 최초의 가 설을 귀무 가설(Null hypothesis)이라고 한다.
   데이터에  의해서  실제로  계산된  숫자, 즉, 검정  통계치가  해당  검정  통계  분포에서  나올 수  있는  확률을  계산한다. 이를  유의  확률(p-value)라고  한다.
   만약  유의  확률이  미리  정한  특정한  기준  값보다  작은  경우를  생각하자. 이  기준  값을 유의  수준(significance level)이라고  하는  데  보통  1% 혹은  5% 정도의  작은  값을  지정한 다. 유의  확률이  유의  수준으로  정한  값(예  1%)보다도  작다는  말은  해당  검정  통계  분포 에서  이  검정  통계치가  나올  수  있는  확률이  아주  작다는  의미이므로  가장  근본이  되는 가설  즉, 귀무  가설이  틀렸다는  의미이다. 따라서  이  경우에는  귀무  가설을  기각(reject) 한다.
   만약 유의 확률이 유의 수준보다 크다면 해당 검정 통계 분포에서 이 검정 통계치가 나 오는 것이 불가능하지만은 않다는 의미이므로 귀무 가설을 기각할 수 없다. 따라서 이 경우에는 귀무 가설을 채택(accept)한다.

    linspace 함수는 numpy모듈의 1차원 배열 만드는 함수
    x = np.linspace(start,stop,num) # num은 요소의 개수 그 사이에 몇개를 만들것인가.
    np.random.randit : 균일 분포의 정수 난수 1개 생서
    np.random.rand : 0부터 1사이의 난수 matrix array 생성
    np.random.randn : 가우시안 표준 정규 분포에서 난수 matrix array 생성
    plt.fill_between() : 두 수평 방향의 곡선 사이를 채웁니다.
    plt.fill_betweenx() : 두 수평 방향의 곡선 사이를 채웁니다.
    plt.fill() : 다각형 영역을 채웁니다.

    파이썬 플랏 상세 설명 : https://blog.naver.com/nach3012/222419686483

"""

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
from scipy import stats
import scipy as sp

font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)

xx1 = np.linspace(-4, 4, 100)
xx2 = np.linspace(-4, -2, 100)
xx3 = np.linspace(2, 4, 100)

plt.fill_between(xx1, sp.stats.norm.pdf(xx1), facecolor='green', alpha=0.1)
plt.fill_between(xx2, sp.stats.norm.pdf(xx2), facecolor='blue', alpha=0.35)
plt.fill_between(xx3, sp.stats.norm.pdf(xx3), facecolor='blue', alpha=0.35)
plt.text(-3, 0.1, "p-value=%5.3f" % (2*sp.stats.norm.cdf(-2)), horizontalalignment='center')
plt.title("유의확률:0.046")
plt.show()