├── README.md
├── aula-4-visualizacao.Rmd
├── aula-3-pandas.Rmd
├── aula-2-numpy.ipynb
└── aula-1-intro.ipynb
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # python4stats
4 |
5 | **Python para Estatística** é um grupo de estudos de Python para análise
6 | de dados. Os estudos irão enfatizar algoritmos, lógica de programação e
7 | estrutura de dados em Python, manipulação e visualização de dados,
8 | estatística descritiva e ajuste de modelos de regressão
9 |
10 | A jornada de estudos aconteceu em 5 módulos de 2 horas cada nos dias
11 | 15, 17, 19, 24 e 26 de Janeiro de 2018, no período das 14h às 16h no
12 | Laboratório de Estatística e Geoinformação (LEG, prédio do Setor de
13 | Ciências Exatas, sala 232).
14 |
15 | O grupo de estudos foi coordenado pelos professores Wagner Bonat,
16 | Walmes Zeviani e Fernando Mayer (LEG/DEST).
17 |
18 | ## Tópicos
19 |
20 | 1. Configuração do ambiente e estruturas de programação
21 | (`aula-1-intro.ipynb`).
22 | 1. Download e instalação do Python e editores.
23 | 2. Módulos, aritmética, lógica, objetos.
24 | 3. Controles de execução e funções.
25 | 2. Álgebra matricial e otimização com `numpy` (`aula-2-numpy.ipynb`).
26 | 1. Operações matriciais.
27 | 2. Distribuições de probabilidade.
28 | 3. Otimização numérica.
29 | 3. Manipulação de dados com `pandas` (`aula-3-pandas.Rmd`).
30 | 1. Leitura de dados no formato texto.
31 | 2. Medidas descritivas.
32 | 3. Manipulação de dados.
33 | 4. Tarefas de split-apply-combine.
34 | 4. Visualização de dados com `matplotlib` (`aula-4-visualizacao.Rmd`).
35 | 1. Gráficos para uma variável.
36 | 2. Gráficos para pares de variáveis.
37 | 5. Modelagem estatística (`aula-5-model.ipynb`).
38 | 1. Modelos de regressão.
39 |
40 | ## Referências
41 |
42 | 1. Grus, J. (2015). *Data science from scratch: first principles with
43 | Python*. Sebastopol, CA: O'Reilly.
44 | 2. Hilpisch, Y. (2014). *Python for finance*. Sebastopol, CA: O'Reilly
45 | Media.
46 | 3. Dale, K. (2016). *Data visualization with Python and JavaScript:
47 | scrape, clean, explore & transform your data*. Sebastopol, CA:
48 | O'Reilly Media.
49 | 4. Menezes, N. N. C. (2014). *Introdução a programação com Python:
50 | algoritmos e lógica de programação para iniciantes*. Novatec, 2014.
51 |
--------------------------------------------------------------------------------
/aula-4-visualizacao.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Visualização de Dados com MatPlotLib e Pandas"
3 | subtitle: "Grupo de Estudos de Python para Análise de Dados"
4 | author: "Walmes Zeviani"
5 | output:
6 | html_document:
7 | theme: flatly
8 | toc: true
9 | number_sections: true
10 | ---
11 |
12 | 1. Distribuições de probabilidade e frequência
13 | 1. histograma
14 | 2. densidade
15 | 3. ecdf
16 | 4. boxplot
17 | 5. barras
18 | 2. Relação entre variáveis
19 | 1. dispersão
20 | 2. boxplot
21 | 3. barras
22 | 4. mosaicplot
23 | 5. pares de diagramas
24 | 3. Anotações e geometria
25 | 1. pontos
26 | 2. linhas
27 | 3. poligonos
28 | 4. curvas
29 | 5. eixos
30 | 6. texto
31 | 7. legenda
32 |
33 | ```{python}
34 | import numpy as np
35 | import pandas as pd
36 | print(pd.__version__)
37 |
38 | import matplotlib.pyplot as plt
39 |
40 | # sudo pip3 install seaborn
41 | import seaborn as sb
42 | ```
43 |
44 | # Gráficos para uma variável
45 |
46 | ## Histogramas
47 |
48 | ```{python}
49 | #-----------------------------------------------------------------------
50 | # Leitura dos dados.
51 |
52 | # Dados de imóveis de 7 bairros em CWB.
53 | u = "http://leg.ufpr.br/~walmes/data/ap_venda7bairros_cwb_210314.txt"
54 | imov = pd.read_table(u)
55 |
56 | # Informações.
57 | imov.info()
58 |
59 | # Extremidades.
60 | imov.head()
61 | imov.tail()
62 |
63 | # Modifica algumas variáveis.
64 | imov.preco = imov.preco/1000
65 | # imov.area = imov.area/1000
66 |
67 | # Descrição de uma delas.
68 | imov.preco.describe()
69 |
70 | # Documentação.
71 | # help(imov.plot.hist)
72 |
73 | #--------------------------------------------
74 | # Histogramas.
75 |
76 | # Histograma do preço na escala original.
77 | imov['preco'].plot.hist(bins = 30)
78 | plt.show()
79 |
80 | # Histograma do preço na escala log.
81 | np.log(imov['preco']).plot.hist(bins = 30)
82 | plt.show()
83 |
84 | np.log(imov['preco']).plot.hist(bins = 30,
85 | # orientation = 'horizontal',
86 | cumulative = True)
87 | plt.show()
88 |
89 | #--------------------------------------------
90 | # Densidade suavizada.
91 |
92 | imov.columns
93 |
94 | np.log(imov['preco']).plot.density(color = 'red')
95 | plt.show()
96 |
97 | np.log(imov['area']).plot.density(color = 'magenta')
98 | plt.show()
99 |
100 | imov[['quartos', 'banheiros']].plot.density(
101 | color = ['red', 'green'])
102 | plt.show()
103 |
104 | #-----------------------------------------------------------------------
105 | # Frequência acumulada.
106 |
107 | # Vetor com valores ordenados.
108 | x = imov.area.sort_values()
109 | x = imov.quartos.sort_values()
110 | x.head()
111 | x.tail()
112 |
113 | # Frequências acumuladas.
114 | px = np.linspace(0., 1., len(x))
115 |
116 | # Vrifica os tamanhos.
117 | len(x) == len(px)
118 |
119 | # Gráfico de distribuição de frequência relativa acumulada.
120 | plt.plot(x, px, drawstyle = 'steps')
121 | plt.show()
122 |
123 | #-----------------------------------------------------------------------
124 | # Gráfico de caixas.
125 |
126 | np.log(imov[['preco']]).plot.box()
127 | plt.show()
128 |
129 | imov[['quartos', 'banheiros', 'vagas']].plot.box()
130 | plt.show()
131 |
132 | #-----------------------------------------------------------------------
133 | # Gráfico de barras.
134 |
135 | imov['ratio'] = imov.preco/imov.area
136 |
137 | imov.columns
138 |
139 | by_bair = imov.groupby('bairro')
140 |
141 | # Tabela resumo com o número de imóveis por bairro.
142 | by_bair.size()
143 |
144 | by_bair.size().plot(kind = 'bar')
145 | plt.show()
146 |
147 | by_bair.size().plot(kind = 'barh')
148 | plt.show()
149 |
150 | by_bair['preco'].median().plot(kind = 'bar')
151 | plt.show()
152 |
153 | by_bair['area'].median().plot(kind = 'barh')
154 | plt.show()
155 |
156 | by_bair['ratio'].mean().plot(kind = 'bar')
157 | plt.show()
158 |
159 | #--------------------------------------------
160 | # Duas variáveis agrupadoras.
161 |
162 | # Converte bairro para categórica.
163 | imov.bairro = imov.bairro.astype('category')
164 | imov.bairro.values
165 |
166 | keep = imov.bairro.isin(['batel', 'portao'])
167 | imovs = imov[keep]
168 | imovs.info()
169 |
170 | by_bair_vag = imovs.groupby(['bairro', 'vagas'])
171 |
172 | ctb = by_bair_vag.size()
173 | ctb
174 |
175 | ctb.plot(kind = 'barh')
176 | plt.show()
177 |
178 | ctb = by_bair_vag.size().unstack().T
179 | ctb
180 |
181 | ctb.plot(kind = 'barh')
182 | plt.show()
183 | ```
184 |
185 | ## Gráficos para duas ou mais variáveis
186 |
187 | ```{python}
188 | #-----------------------------------------------------------------------
189 | # Diagrama de dispersão.
190 |
191 | ax = imov.plot.scatter(x = 'area', y = 'preco')
192 |
193 | ax.set_yscale('log')
194 | ax.set_xscale('log')
195 | plt.show()
196 |
197 | #-----------------------------------------------------------------------
198 |
199 | by_bair = imov.groupby(['bairro'])
200 |
201 | by_bair.size()
202 | by_bair[['preco', 'area']].head()
203 |
204 | ax = by_bair.get_group('batel').plot.scatter(x = 'area',
205 | y = 'preco',
206 | color = 'DarkBlue',
207 | label = 'Batel')
208 | ax.set_yscale('log')
209 | ax.set_xscale('log')
210 | ax.xlabel('Log do preço (R$/1000)')
211 | ax.ylabel('Log da área (m^2/1000)')
212 | by_bair.get_group('portao').plot.scatter(x = 'area',
213 | y = 'preco',
214 | color = 'DarkGreen',
215 | label = 'Portão',
216 | ax = ax)
217 | plt.show()
218 | ```
219 |
220 | # Referências
221 |
222 | 1. Livros
223 | 1. Dale, K. (2016). *Data visualization with Python and JavaScript:
224 | scrape, clean, explore & transform your data*. Sebastopol, CA:
225 | O'Reilly Media. Homepage:
226 | . Source
227 | code: .
228 | 2. Massaron, L. & Mueller, J. (2015). *Python for data science for
229 | dummies*. Hoboken, NJ: John Wiley and Sons, Inc. Homepage:
230 | .
231 | Source code:
232 |
233 | 2. Webpages
234 | 1. .
235 | 2.
236 | 3. .
237 | 4. .
238 | 5. Chris Albon webpage: .
239 | 6. `ggplot` para Python: .
240 | 3. Cheat sheets
241 |
242 |
243 | [`Series`]: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
244 | [`DataFrame`]: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
245 |
--------------------------------------------------------------------------------
/aula-3-pandas.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Manipulação de Visualização de Dados"
3 | subtitle: "Grupo de Estudos de Python para Análise de Dados"
4 | author: "Walmes Zeviani"
5 | output:
6 | html_document:
7 | theme: flatly
8 | toc: true
9 | number_sections: true
10 | ---
11 |
12 | # Tabela de conteúdo
13 |
14 | 1. Habilitar Python no Emacs
15 | 1. `.emacs` e pacotes.
16 | 2. path para o Anaconda Python
17 | 2. Introdução ao Pandas.
18 | 1. Classes `Series` e `DataFrame`.
19 | 2. Iniciando objetos das classes.
20 | 3. Acesso as propriedades e métodos.
21 | 4. Indexação e seleção.
22 | 5. Modificação de conteúdo.
23 | 6. Modificação de atributos.
24 | 3. Manipulação de dados.
25 | 1. Datasets internos do Python.
26 | 2. Filtros e ordenação.
27 | 3. Criar e excluir registros e variáveis.
28 | 4. Empilhar e fundir tabelas.
29 | 5. Estatística descritiva.
30 | 6. Estatísticas por estrato.
31 | 4. Leitura de arquivos de dados.
32 | 1. Com separador de campo: CSV e TSV.
33 | 2. De campo de comprimento fixo.
34 | 3. Planilhas eletrônicas.
35 | 5. Visualização de dados.
36 | 1. Modelo mental do Python.
37 |
38 | # Python dentro do Emacs
39 |
40 | As instruções a seguir são para habilitação minimalista do Python dentro
41 | do emacs.
42 |
43 | Instale o pacote `elpy` no seu Emacs. De dentro de uma sessão emacs faça
44 | `M-x package-list-packages`. Em seguida, procure pelo `elpy` com `C-s
45 | elpy`. Com o cursor nessa linha, pressione `i` para selecionar o pacote
46 | para instalação e `x` para executar a instalação. Aguarde até o final do
47 | processo.
48 |
49 | Coloque no seu arquivo `.emacs` o seguinte conteúdo.
50 |
51 | ```{lisp, eval = FALSE}
52 | ;;----------------------------------------------------------------------
53 | ;; Python configuration.
54 |
55 | ;; Install first: M-x package-list-packages C-s elpy.
56 | (elpy-enable)
57 |
58 | ;; Define o interpretador Python.
59 | (custom-set-variables
60 | ;; '(python-shell-interpreter "~/anaconda/bin/python3")
61 | '(python-shell-interpreter "/usr/bin/python3")
62 | )
63 |
64 | ;; Habilita autocomplete após os pontos.
65 | (setq jedi:complete-on-dot t)
66 |
67 | ;; Python3 console, C-c C-p para abrir o console
68 | (defcustom python-shell-interpreter "python3"
69 | "Default Python interpreter for shell."
70 | :type 'string
71 | :group 'python)
72 |
73 | ;;----------------------------------------------------------------------
74 | ```
75 |
76 | A partir de agora, quando abrir arquivos `.py`, o modo Python
77 | (`python-mode`) estará operando. Faça `C-RET` para avaliar uma linha ou
78 | região selecionada. Na primeira execução o console Python será aberto em
79 | um buffer paralelo.
80 |
81 | # Configuração para usar Python com Rmarkdown
82 |
83 | Indicar o caminho para o interpretador Python no primeiro chunk.
84 |
85 | ```{r setup, include = TRUE}
86 | # Usa o Python 3.x para processar os chunks.
87 | knitr::opts_chunk$set(
88 | engine.path = "/usr/bin/python3")
89 | ```
90 |
91 | Verificar se a versão vista ao processar o documento é de fato a versão
92 | pretendida.
93 |
94 | ```{python}
95 | # Exibe a versão da engine Python sendo usada.
96 | import sys
97 | print(sys.version)
98 | ```
99 |
100 | No caso de ausência de pacotes, executar em terminal shell as instruções
101 | abaixo para instalação dos pacotes.
102 |
103 | ```
104 | # Instala pacotes no Python 3.x.
105 | sudo apt-get install python3-pip
106 | sudo pip3 install numpy scipy pandas matplotlib scikit-learn
107 | sudo apt-get install python3-tk
108 |
109 | # Para instalar o Jupyter e o Spyder.
110 | sudo pip3 install jupyter
111 | sudo pip3 install spyder
112 | ```
113 |
114 | Varificar se os gráficos estão sendo inseridos dentro do documento.
115 |
116 | ```{python}
117 | # Importa bibliotecas gráficas.
118 | import matplotlib as mpl
119 | import matplotlib.pyplot as plt
120 |
121 | # Cria um gráfico simples.
122 | plt.plot([1,2,3,4])
123 | plt.show()
124 | ```
125 |
126 | Segundo discussão no [issues/812] do repositório do rmarkdown, é
127 | possível usar o Python fornecido pelo Anaconda.
128 |
129 | IMPORTANTE: estar com a última versão do pacote `rmarkdown`. Instalar a
130 | versão disponível no github. É necessário instalar o pacote
131 | `reticulate` que é chamado quando a engine é Python.
132 |
133 | ```{r, eval = FALSE}
134 | devtools::install_github("rstudio/rmarkdown")
135 | install.packages("reticulate")
136 | ```
137 |
138 | # Introdução ao Pandas
139 |
140 | O tipo "primitivo" de objeto fornecido pelo Pandas é o [`Series`]. Nada
141 | mais é que o nome para um vetor de dados. Ele é contruido a partir do
142 | `numpy.array()`.
143 |
144 | ```{python}
145 | # Importa o módulo.
146 | import pandas as pd
147 |
148 | # Exibe a documentação.
149 | # help(pd.Series)
150 |
151 | # Criando um objeto tipo Series.
152 | s = pd.Series(range(10))
153 | print(s)
154 |
155 | # Atributos da classe (não termina com parênteses.)
156 | print(s.dtype)
157 | print(s.nbytes)
158 | print(s.shape)
159 | print(s.values)
160 |
161 | type(s)
162 |
163 | # (funções) Métodos associadas a classe.
164 | # ATTENTION: mostrar recursos de REGEX do Emacs para colocar o print().
165 | s.min()
166 | s.max()
167 | s.mean()
168 | s.median()
169 | s.std()
170 | s.head(3)
171 | s.tail(3)
172 | s.describe()
173 | ```
174 |
175 | O [`DataFrame`] é o tipo de objeto que representa a tabela de dados. Ele é
176 | contruído a partir do `Series`.
177 |
178 | ```{python}
179 | # Dicionário com listas de mesmo tamanho.
180 | d = {'grr': [1, 2, 3, 4],
181 | 'nome': ["Andre", "Gabriela", "Rodrigo", "Tatiana"],
182 | 'nota': [9.0, 9.2, 7.9, 8.3]}
183 | d
184 |
185 | # Conversão para DataFrame.
186 | df = pd.DataFrame(data = d)
187 | df
188 |
189 | # Atributos.
190 | df.shape # Comprimento em cada dimensão.
191 | df.size # Número de entradas.
192 | df.axes # Nome dos eixos.
193 | df.values # Representação NumPy.
194 | df.dtypes # Tipagem de cada coluna.
195 |
196 | # Acesso as `Series`. Pelo nome não pode haver espaços.
197 | df.grr
198 | df.nome
199 | df.nota
200 |
201 | # Pelo nome dos índices. Permite mais de uma coluna.
202 | df[['nota']]
203 | df[['nota', 'nome']]
204 |
205 | # Por sequência de posições.
206 | df.iloc[:,1:3]
207 |
208 | # Seleção de linhas (três formas equivalentes).
209 | df.iloc[1:3]
210 | df.iloc[1:3,]
211 | df.iloc[1:3,:]
212 |
213 | # Seleção de linhas e colunas.
214 | df.iloc[1:3, 0:2]
215 | # df.iloc[1:3, ['nome', 'grr']]
216 | df.iloc[1:3, ][['nome', 'grr']]
217 |
218 | # Retonar o nome das colunas.
219 | df.columns
220 | df.columns[-2] # É uma lista.
221 | df.columns[[0, 2]] # É uma lista.
222 |
223 | # Usar as opções combinadas (passando a lista).
224 | df.iloc[1:3, ][df.columns[-2]]
225 |
226 | df[[0, 2]]
227 | df.iloc[:, [0, 2]]
228 | df.iloc[[0, 2], [0, 2]]
229 | df.iloc[[0, 2]]
230 | df.iloc[[0, 2],]
231 | df.iloc[[0, 2],:]
232 |
233 | x = range(0, 3, 2)
234 | df.iloc[x,:]
235 | df.iloc[0:3:2,:]
236 |
237 | # Com intervalo dado pelo nome dos extremos.
238 | df.loc[:, 'grr':'nota']
239 |
240 | # Dar nome para as linhas.
241 | df = df.set_index('grr')
242 | df
243 |
244 | # `grr` deixou de ser uma coluna para der o ID.
245 | df.columns
246 |
247 | # Restaura o índice e retorna `grr` como coluna.
248 | df.reset_index(inplace = True)
249 | df.columns
250 |
251 | # Usa nome como índice dos registros.
252 | df = df.set_index('nome')
253 | df.columns
254 | df
255 |
256 | # Seleciona linhas pelo nome do índice.
257 | df.loc["Andre"]
258 | df.loc["Tatiana"]
259 |
260 | # Pela posição.
261 | df.iloc[0]
262 | df.iloc[-1]
263 |
264 | # Mudar o nome das colunas.
265 | df.columns = ['Grr', 'Nota']
266 | df
267 |
268 | df.rename(columns = {'Grr': 'GRR',
269 | 'Nota': 'nota'},
270 | inplace = True)
271 | df
272 |
273 | # Estrutura do DataFrame.
274 | df.info()
275 |
276 | # Medidas descritivas para variáveis numéricas.
277 | df.describe()
278 |
279 | # Restaura o índice.
280 | df.reset_index(inplace = True)
281 | df
282 |
283 | # Adiciona um registro ao final da tabela (usa dict).
284 | df = pd.DataFrame(data = d)
285 | df
286 | df = df.append({'grr': 5, 'nota': 10, 'nome': 'Pedro', 'falta': 6},
287 | ignore_index = True)
288 | df
289 |
290 | df = df.append(pd.DataFrame({'grr': [6, 7], 'nota': [10, 9], 'nome':
291 | ['Maicon', 'Maria'], 'falta': [6, 0]}),
292 | ignore_index = True)
293 | df
294 |
295 | # Exclui o registro pelo índice.
296 | df.drop([3], inplace = True)
297 | df
298 |
299 | dg = pd.DataFrame([[99, 'Carolina', 9.5, 8],
300 | [98, 'Lígia', 7.1, 10]],
301 | columns = ['grr', 'nome', 'nota', 'falta'])
302 | dg
303 |
304 | # Empilha duas tabelas.
305 | df.append(dg)
306 | df.append(dg, ignore_index = True)
307 | df
308 | dg
309 |
310 | # Remove uma colunas.
311 | df.drop(['falta'], axis = 1)
312 | df
313 |
314 | # Criando uma coluna.
315 | df.falta = pd.Series([10, 0, 4, 2, 18, 16],
316 | index = df.index)
317 | df
318 | ```
319 |
320 | # Manipulação de dados
321 |
322 | ```{r, eval = FALSE}
323 | u <- "http://leg.ufpr.br/~walmes/data/triathlon.txt"
324 | download.file(u, destfile = basename(u))
325 | getwd()
326 | dir()
327 | ```
328 |
329 | ## Importação de TSV
330 |
331 | ```{python}
332 | # Lendo um TSV.
333 | cap = pd.read_table('http://leg.ufpr.br/~walmes/data/desfolha.txt')
334 |
335 | # Informações.
336 | cap.info()
337 |
338 | # Exibe a tabela.
339 | cap
340 |
341 | # Medidas descritivas para as variáveis numéricas.
342 | cap.describe()
343 |
344 | # Descrição pelo tipo de variável.
345 | cap.describe(include = 'int')
346 | cap.describe(include = 'float')
347 | cap.describe(include = ['int', 'float'])
348 | cap.describe(include = 'object')
349 | cap.describe(include = 'all')
350 | ```
351 |
352 | ## Medidas descritivas por estrato
353 |
354 | ```{python}
355 | # Média por estrato.
356 | cap.groupby(['estag'])['pcapu'].mean()
357 | cap.groupby(['estag'])['pcapu', 'ncapu'].mean()
358 | cap.groupby(['estag', 'desf'])['pcapu', 'ncapu'].mean()
359 | cap.groupby(['estag', 'desf'])['pcapu', 'ncapu'].describe()
360 |
361 | capg = cap.groupby(['estag', 'desf'])
362 | capg
363 |
364 | # Médias de duas variáveis.
365 | m = cap.groupby(['estag'])['pcapu', 'ncapu'].mean()
366 | m
367 | m.reset_index(inplace = True)
368 | m
369 |
370 | # Máximo de uma outra variável,
371 | M = cap.groupby(['estag'])['alt'].max()
372 | M
373 | M = pd.DataFrame(M)
374 | M.reset_index(inplace = True)
375 | M
376 |
377 | pd.merge(m, M, on = ['estag'])
378 | ```
379 |
380 | ## Função com medidas descritivas
381 |
382 | ```{python}
383 | import numpy as np
384 |
385 | cap.groupby(['estag'])['pcapu'].agg({
386 | "media" : np.mean,
387 | "errpd" : np.std,
388 | "ampli" : lambda x: np.max(x) - np.min(x),
389 | "cv" : lambda x: 100 * np.std(x)/np.mean(x)
390 | })
391 |
392 | res = cap.groupby(['estag', 'desf'])['pcapu', 'alt'].agg({
393 | "media" : np.mean,
394 | "errpd" : np.std
395 | })
396 | res
397 |
398 | # Organização do objeto.
399 | res.info()
400 |
401 | # Atributos de linhas e colunas são MultiIndex.
402 | res.columns
403 | res.columns.levels
404 | res.index
405 | res.index.levels
406 |
407 | res.reset_index()
408 | ```
409 |
410 | ## Filtros
411 |
412 | ```{python}
413 | #--------------------------------------------
414 | # Máscaras lógicas.
415 |
416 | cap[cap.alt > 150]
417 | cap[cap['alt'] > 150]
418 |
419 | # IMPORTANT: tem que ter os parenteses.
420 | cap[(cap.alt > 150) & ((cap.ncapu >= 10) | (cap.nnos > 30))]
421 |
422 | #--------------------------------------------
423 | # Partições feitas com o groupby().
424 |
425 | # Com uma variável de agrupamento.
426 | gb = cap.groupby(['estag'])
427 | gb
428 | gb.groups
429 |
430 | gb.get_group('1veg')
431 | gb.get_group('5capu')
432 |
433 | pd.concat([gb.get_group('1veg'),
434 | gb.get_group('5capu')])
435 |
436 | # Com duas variáveis de agrupamento.
437 | gb = cap.groupby(['estag', 'desf'])
438 | gb
439 |
440 | gb.groups
441 |
442 | # Tem que usar uma tupla.
443 | gb.get_group(('1veg', 0))
444 | gb.get_group(('5capu', 100))
445 |
446 | pd.concat([gb.get_group(('1veg', 0)),
447 | gb.get_group(('5capu', 100))])
448 | ```
449 |
450 | ## Ordenação
451 |
452 | ```{python}
453 | cap.sort_values(['alt'], ascending = False).head(10)
454 | cap.sort_values(['ncapu', 'alt']).head(10)
455 | ```
456 |
457 | ## Junção de tabelas
458 |
459 | ```{python}
460 | tabA = pd.DataFrame({
461 | 'nome': ["Marcos", "Julia", "Gabriel"],
462 | 'nota': [8.9, 6.7, 8.1]
463 | })
464 |
465 | tabB = pd.DataFrame({
466 | 'nome': ["Ulisses", "Andrea", "Ana", "Pedro"],
467 | 'nota': [7.7, 7.1, 8.3, 5.0]
468 | })
469 |
470 | tabC = pd.DataFrame({
471 | 'falta': [10, 12, 4, 0],
472 | 'idade': [18, 20, 18, 19]
473 | })
474 | tabC.index = [0, 1, 3, 4] # Index com falha.
475 |
476 | #--------------------------------------------
477 | # Empilhar.
478 |
479 | # Usando append().
480 | tabA.append(tabB)
481 | tabA.append(tabB, ignore_index = True)
482 |
483 | # Usando concat().
484 | pd.concat([tabA, tabB], axis = 0)
485 | pd.concat([tabA, tabB], axis = 0, ignore_index = True)
486 |
487 | #--------------------------------------------
488 | # Lado a lado.
489 |
490 | pd.concat([tabB, tabC], axis = 1)
491 |
492 | #--------------------------------------------
493 | # De formato long para wide e vice versa.
494 |
495 | tab_wide = pd.DataFrame({
496 | 'trat' : ["A", "B", "C"],
497 | 'aval1' : [1, 2, 3],
498 | 'aval2' : [10, 20, 30],
499 | 'aval3' : [100, 200, 300]
500 | })
501 | tab_wide
502 |
503 | tab_long = pd.melt(tab_wide,
504 | id_vars = ['trat'],
505 | var_name = 'x',
506 | value_name = 'y')
507 | tab_long
508 |
509 | # Para complicar, vamos remover uma linha.
510 | tab_long.drop([3], axis = 0, inplace = True)
511 |
512 | tab_wide = tab_long.pivot(index = 'trat',
513 | columns = 'x',
514 | values = 'y')
515 | tab_wide.reset_index(inplace = True)
516 | tab_wide
517 | ```
518 |
519 | # Acesso a documentação interna em PDF
520 |
521 | ```{sh, eval = FALSE}
522 | pydoc3 -p 1234 # Abre o navegador na home da documentação.
523 | ```
524 |
525 | # Referências
526 |
527 | 1. Livros
528 | 1. Dale, K. (2016). *Data visualization with Python and JavaScript:
529 | scrape, clean, explore & transform your data*. Sebastopol, CA:
530 | O'Reilly Media. Homepage:
531 | . Source
532 | code: .
533 | 2. Massaron, L. & Mueller, J. (2015). *Python for data science for
534 | dummies*. Hoboken, NJ: John Wiley and Sons, Inc. Homepage:
535 | .
536 | Source code:
537 |
538 | 2. Webpages
539 | 1. Chris Albon webpage: .
540 | 2. .
541 | 3. .
542 | 3. Cheat sheets
543 | 2.
544 | 3.
545 | 4.
546 | 5.
547 |
548 |
549 | [`Series`]: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
550 | [`DataFrame`]: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
551 | [issues/812]: https://github.com/rstudio/rmarkdown/issues/812
552 |
--------------------------------------------------------------------------------
/aula-2-numpy.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Encontro II\n",
8 | "\n",
9 | "## Objetivo\n",
10 | "\n",
11 | "Neste segundo encontro vamos discutir os seguintes assuntos: \n",
12 | "\n",
13 | " - Estruturas numpy;\n",
14 | " - Álgebra linear usando numpy e modulos associados;\n",
15 | " - Distribuições de probabilidade;\n",
16 | " - Otimização;\n",
17 | " - Integração e derivação numéricas;\n",
18 | " - Exemplos.\n",
19 | "\n",
20 | "A biblioteca `numpy` é o centro de toda computação científica em python. Ela implementa objetos `array` multidimensionais de alta performance e métodos para manipular tais objetos. \n",
21 | "\n",
22 | "## Estruturas numpy\n",
23 | "\n",
24 | "Um `numpy array` é um gride de valores todos de mesmo tipo indexado por um `tuple` de inteiros não negativos. O número de dimensões é o `size` do `array` e o `shape` do `array` é uma `tuple` que mostra o tamanho de cada dimensão. Podemos inicializar arrays usando objetos do tipo `list` e acessar elementos do array usando colchetes (*square brackets*).\n"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 1,
30 | "metadata": {},
31 | "outputs": [
32 | {
33 | "name": "stdout",
34 | "output_type": "stream",
35 | "text": [
36 | "\n",
37 | "3\n",
38 | "(3,)\n",
39 | "[10 2 3]\n",
40 | "[[1 2 3]\n",
41 | " [4 5 6]]\n",
42 | "6\n",
43 | "(2, 3)\n"
44 | ]
45 | }
46 | ],
47 | "source": [
48 | "import numpy as np\n",
49 | "a = np.array([1, 2, 3]) # Cria um array de rank = 1\n",
50 | "print(type(a))\n",
51 | "print(a.size) # Tamanho\n",
52 | "print(a.shape) # Dimensão\n",
53 | "\n",
54 | "a[0] = 10 # Modifica um elemento do array\n",
55 | "print(a)\n",
56 | "\n",
57 | "b = np.array([[1,2,3],[4,5,6]]) # array 2 linhas e 3 colunas\n",
58 | "print(b)\n",
59 | "print(b.size)\n",
60 | "print(b.shape)"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {},
66 | "source": [
67 | "`Numpy` também fornece várias opções para inicializar arrays."
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 16,
73 | "metadata": {},
74 | "outputs": [
75 | {
76 | "name": "stdout",
77 | "output_type": "stream",
78 | "text": [
79 | "[[ 0. 0. 0.]\n",
80 | " [ 0. 0. 0.]\n",
81 | " [ 0. 0. 0.]]\n",
82 | "[[ 1. 1. 1.]\n",
83 | " [ 1. 1. 1.]]\n",
84 | "[[10 10 10 10]\n",
85 | " [10 10 10 10]\n",
86 | " [10 10 10 10]\n",
87 | " [10 10 10 10]]\n",
88 | "[[ 1. 0. 0.]\n",
89 | " [ 0. 1. 0.]\n",
90 | " [ 0. 0. 1.]]\n",
91 | "[[ 0.23672878 0.58462308]\n",
92 | " [ 0.19209855 0.02922875]]\n"
93 | ]
94 | }
95 | ],
96 | "source": [
97 | "a = np.zeros((3,3)) # array de zeros 2x2\n",
98 | "print(a)\n",
99 | "\n",
100 | "b = np.ones((2,3)) # array de 1's 2x3\n",
101 | "print(b)\n",
102 | "\n",
103 | "c = np.full((4,4), 10) # array 4x4 com todas as entradas iguais a 10\n",
104 | "print(c)\n",
105 | "\n",
106 | "d = np.eye(3) # Matrix identidade 3x3\n",
107 | "print(d)\n",
108 | "\n",
109 | "e = np.random.random((2,2)) # Matrix 3x3 de números aleatórios\n",
110 | "print(e)"
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {},
116 | "source": [
117 | "### Acessando elementos do array\n",
118 | "\n",
119 | "Similar a objetos do tipo `list` um `array` pode ser fatiados (*sliced*). Como os arrays são multidimensionais podemos especificar uma fatia para cada dimensão do `array`."
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "execution_count": 71,
125 | "metadata": {},
126 | "outputs": [
127 | {
128 | "name": "stdout",
129 | "output_type": "stream",
130 | "text": [
131 | "(3, 4)\n",
132 | "[1 2 3 4]\n",
133 | "[[1 2 3 4]\n",
134 | " [5 6 7 8]]\n",
135 | "[ 9 10 11 12]\n"
136 | ]
137 | }
138 | ],
139 | "source": [
140 | "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) # array \n",
141 | "print(a.shape) # 3x4\n",
142 | "print(a[0,]) # Primeira linha\n",
143 | "print(a[0:2,]) # Primeira e segunda linha\n",
144 | "print(a[2,]) # Terceira linha"
145 | ]
146 | },
147 | {
148 | "cell_type": "markdown",
149 | "metadata": {},
150 | "source": [
151 | "Acessando as colunas do `array`."
152 | ]
153 | },
154 | {
155 | "cell_type": "code",
156 | "execution_count": 72,
157 | "metadata": {},
158 | "outputs": [
159 | {
160 | "name": "stdout",
161 | "output_type": "stream",
162 | "text": [
163 | "[[ 3 4]\n",
164 | " [ 7 8]\n",
165 | " [11 12]]\n",
166 | "[ 4 8 12]\n",
167 | "[[ 3]\n",
168 | " [ 7]\n",
169 | " [11]]\n"
170 | ]
171 | }
172 | ],
173 | "source": [
174 | "print(a[:,2:4]) # Terceira e quarta coluna\n",
175 | "print(a[:,3]) # Apenas a quarta coluna rsrs\n",
176 | "print(a[:,2:3]) # Isso é estranho!!"
177 | ]
178 | },
179 | {
180 | "cell_type": "markdown",
181 | "metadata": {},
182 | "source": [
183 | "Acessando elementos específicos."
184 | ]
185 | },
186 | {
187 | "cell_type": "code",
188 | "execution_count": 85,
189 | "metadata": {},
190 | "outputs": [
191 | {
192 | "name": "stdout",
193 | "output_type": "stream",
194 | "text": [
195 | "[7 8]\n",
196 | "[[100 3]\n",
197 | " [ 6 7]]\n",
198 | "[[ 1 100 3 4]\n",
199 | " [ 5 6 7 8]\n",
200 | " [ 9 10 11 12]]\n",
201 | "[[50 3]\n",
202 | " [ 6 7]]\n",
203 | "[[ 1 100 3 4]\n",
204 | " [ 5 6 7 8]\n",
205 | " [ 9 10 11 12]]\n"
206 | ]
207 | }
208 | ],
209 | "source": [
210 | "a[1,1] # Segunda linha segunda coluna\n",
211 | "print(a[1,2:4]) # Segunda linha colunas 3 e 4.\n",
212 | "\n",
213 | "# Tirando apenas uma fatia do array e criando um novo\n",
214 | "b = a[:2, 1:3]\n",
215 | "print(b) \n",
216 | "# Mais cuidado os objetos ainda são os mesmos\n",
217 | "b[0,0] = 100\n",
218 | "print(a) \n",
219 | "\n",
220 | "# Evitando esse comportamento usando função deepcopy do module copy\n",
221 | "from copy import deepcopy\n",
222 | "c = deepcopy(a[:2, 1:3])\n",
223 | "c[0,0] = 50\n",
224 | "print(c)\n",
225 | "print(a)"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {},
231 | "source": [
232 | "Capturar pedaços de um `array` que não sejam fatias é um pouco mais complicado. \n",
233 | "Suponha que queremos capturar a primeira e terceira linhas."
234 | ]
235 | },
236 | {
237 | "cell_type": "code",
238 | "execution_count": 94,
239 | "metadata": {},
240 | "outputs": [
241 | {
242 | "name": "stdout",
243 | "output_type": "stream",
244 | "text": [
245 | "[[ 1 2 3 4]\n",
246 | " [ 5 6 7 8]\n",
247 | " [ 9 10 11 12]]\n",
248 | "[[100 2 3 4]\n",
249 | " [ 9 10 11 12]]\n",
250 | "(2, 4)\n"
251 | ]
252 | }
253 | ],
254 | "source": [
255 | "a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
256 | "b = np.array([a[0,],a[2,]]) # novo array\n",
257 | "b[0,0] = 100\n",
258 | "print(a) # note que agora realmente temos um novo array que não altera o array anterior\n",
259 | "print(b)\n",
260 | "print(b.shape) #2x4"
261 | ]
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {},
266 | "source": [
267 | "Importante entender o que acontece com objetos `array`. Quando capturamos um `slice` do `array` a fatia capturada ainda é parte do `array` original e portanto qualquer modificação na fatia vai mudar também o `array`. Entretanto, quando capturamos fatias ou pedaços de um `array` e com essas fatias ou pedaços criamos um novo `array` que portanto não é mais parte do `array` original. Assim, mudanças no novo `array` não afetaram o `array` original."
268 | ]
269 | },
270 | {
271 | "cell_type": "markdown",
272 | "metadata": {},
273 | "source": [
274 | "Podemos selecionar elementos de um `array` usando variáveis boleanas. "
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": 96,
280 | "metadata": {},
281 | "outputs": [
282 | {
283 | "data": {
284 | "text/plain": [
285 | "array([ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])"
286 | ]
287 | },
288 | "execution_count": 96,
289 | "metadata": {},
290 | "output_type": "execute_result"
291 | }
292 | ],
293 | "source": [
294 | "a[a > 2]"
295 | ]
296 | },
297 | {
298 | "cell_type": "markdown",
299 | "metadata": {},
300 | "source": [
301 | "Existem muitas opções de como manipular e capturar fatias e/ou pedaços de `array` usando `numpy` para mais detalhes ver (http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)."
302 | ]
303 | },
304 | {
305 | "cell_type": "markdown",
306 | "metadata": {},
307 | "source": [
308 | "## Álgebra linear usando `numpy`\n",
309 | "\n",
310 | "A classe `ndarray` disponibilizada pela biblioteca `numpy` é muito geral e flexível. Entretanto, em estatística em geral estamos interessados em matrizes. Uma matriz nada mais é do que um `array` bidimensional. Devido a sua importância não apenas em estatística mais em diversas áreas a biblioteca `numpy` oferece ferramentas específicas para trabalhar com matrizes em python. Para inicializar uma matriz em python o processo é muito similar a inicialização de um `array`. O interessante é que agora operações matemáticas simples podem ser feitas em todos os elementos da matriz que pode ser apenas um vetor linha ou coluna como mostra o código abaixo."
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 9,
316 | "metadata": {},
317 | "outputs": [
318 | {
319 | "name": "stdout",
320 | "output_type": "stream",
321 | "text": [
322 | "[[2 4 6]]\n",
323 | "[[2]\n",
324 | " [4]\n",
325 | " [6]]\n",
326 | "[[ 1. 1.41421356 1.73205081]]\n",
327 | "[[ 2.71828183 7.3890561 20.08553692]]\n",
328 | "[[ 0. 0.69314718 1.09861229]]\n",
329 | "[[2 4 6]]\n",
330 | "[[0]\n",
331 | " [0]\n",
332 | " [0]]\n",
333 | "[[ 1. 1. 1.]]\n",
334 | "[[1 4 9]]\n"
335 | ]
336 | }
337 | ],
338 | "source": [
339 | "a = np.matrix([[1,2,3]]) # vetor linha\n",
340 | "a.shape\n",
341 | "b = a.T # transposto (vetor coluna)\n",
342 | "\n",
343 | "print(a * 2) # Multiplicação por constante\n",
344 | "print(b * 2)\n",
345 | "\n",
346 | "print(np.sqrt(a)) # Raiz de cada elemento de a\n",
347 | "print(np.exp(a)) # Exponencial de cada elemento de a\n",
348 | "print(np.log(a)) # Logaritmo de cada elemento de a\n",
349 | "\n",
350 | "print(a + a) # Soma dois vetores (elementwise)\n",
351 | "print(b - b) # Subtrai dois vetores\n",
352 | "print(a/a) # Divisão elementwise\n",
353 | "print(np.multiply(a,a)) # multiplicação elementwise"
354 | ]
355 | },
356 | {
357 | "cell_type": "markdown",
358 | "metadata": {},
359 | "source": [
360 | "Para inicializar uma matriz usando a `numpy` usamos uma sintaxe parecida com a inicialização de uma `list`."
361 | ]
362 | },
363 | {
364 | "cell_type": "code",
365 | "execution_count": 3,
366 | "metadata": {},
367 | "outputs": [
368 | {
369 | "name": "stdout",
370 | "output_type": "stream",
371 | "text": [
372 | "(3, 3)\n",
373 | "(3, 3)\n"
374 | ]
375 | }
376 | ],
377 | "source": [
378 | "A = np.matrix([ [1, 0.8, 0.6], [0.8, 1, 0.4], [0.6, 0.4, 1]])\n",
379 | "B = np.matrix([ [1, 0.2, 0.3], [0.2, 1, 0.5], [0.3, 0.5, 1]])\n",
380 | "print(A.shape)\n",
381 | "print(B.shape)"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {},
387 | "source": [
388 | "Operações matriciais são executadas de forma intuitiva."
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": 7,
394 | "metadata": {},
395 | "outputs": [
396 | {
397 | "name": "stdout",
398 | "output_type": "stream",
399 | "text": [
400 | "[[ 2. 1. 0.9]\n",
401 | " [ 1. 2. 0.9]\n",
402 | " [ 0.9 0.9 2. ]]\n",
403 | "[[ 0. 0.6 0.3]\n",
404 | " [ 0.6 0. -0.1]\n",
405 | " [ 0.3 -0.1 0. ]]\n",
406 | "[[ 1.34 1.3 1.3 ]\n",
407 | " [ 1.12 1.36 1.14]\n",
408 | " [ 0.98 1.02 1.38]]\n",
409 | "[ 1. 1. 1.]\n",
410 | "[[ 2.71828183 2.22554093 1.8221188 ]\n",
411 | " [ 2.22554093 2.71828183 1.4918247 ]\n",
412 | " [ 1.8221188 1.4918247 2.71828183]]\n"
413 | ]
414 | }
415 | ],
416 | "source": [
417 | "print(A + B) # Soma Elementwise\n",
418 | "print(A - B) # Subtração\n",
419 | "print(np.dot(A,B)) # Multiplicação matricial\n",
420 | "print(np.diag(A)) # Pega só a diagonal\n",
421 | "print(np.exp(A)) # Exponencial de cada entrada - util para geoestatística ;)"
422 | ]
423 | },
424 | {
425 | "cell_type": "markdown",
426 | "metadata": {},
427 | "source": [
428 | "As principais operações de álgebra linear estão implementadas em um modulo extra da `numpy` chamado de `numpy.linalg`. Sendo, vamos importar a biblioteca `numpy.linalg` usando apenas o prefixo `lp` e fazer algumas operações matriciais básicas como inversão, cálculo de determinantes e decomposições de autovalor e autovetor e Cholesky. Também podemos obter algumas propriedades da matrix como sua norma e rank."
429 | ]
430 | },
431 | {
432 | "cell_type": "code",
433 | "execution_count": 9,
434 | "metadata": {},
435 | "outputs": [
436 | {
437 | "name": "stdout",
438 | "output_type": "stream",
439 | "text": [
440 | "[[ 3.75 -2.5 -1.25 ]\n",
441 | " [-2.5 2.85714286 0.35714286]\n",
442 | " [-1.25 0.35714286 1.60714286]]\n",
443 | "0.224\n",
444 | "(array([ 2.21493472, 0.16242348, 0.6226418 ]), matrix([[ 0.63457746, 0.75716113, -0.15497893],\n",
445 | " [ 0.58437383, -0.60130182, -0.54492509],\n",
446 | " [ 0.50578521, -0.25523155, 0.82403773]]))\n",
447 | "[[ 1. 0. 0. ]\n",
448 | " [ 0.8 0.6 0. ]\n",
449 | " [ 0.6 -0.13333333 0.78881064]]\n",
450 | "2.30651251893\n",
451 | "3\n"
452 | ]
453 | }
454 | ],
455 | "source": [
456 | "import numpy.linalg as lp\n",
457 | "\n",
458 | "print(lp.inv(A)) # inverse de A\n",
459 | "print(lp.det(A)) # determinante de A\n",
460 | "\n",
461 | "print(lp.eig(A)) # Autovalores e autovetores\n",
462 | "print(lp.cholesky(A)) # Decomposição de Cholesky\n",
463 | "\n",
464 | "print(lp.norm(A)) # Norma\n",
465 | "print(lp.matrix_rank(A)) # Rank (numero de colunas li)"
466 | ]
467 | },
468 | {
469 | "cell_type": "markdown",
470 | "metadata": {},
471 | "source": [
472 | "Outra ferramenta muito útil é a solução de sistemas lineares do tipo $Ax = b$. Em python isso é facilmente implementado, novamente usando o modulo `numpy.linalg`."
473 | ]
474 | },
475 | {
476 | "cell_type": "code",
477 | "execution_count": 11,
478 | "metadata": {},
479 | "outputs": [
480 | {
481 | "data": {
482 | "text/plain": [
483 | "matrix([[-5. ],\n",
484 | " [ 4.28571429],\n",
485 | " [ 4.28571429]])"
486 | ]
487 | },
488 | "execution_count": 11,
489 | "metadata": {},
490 | "output_type": "execute_result"
491 | }
492 | ],
493 | "source": [
494 | "A = np.matrix([ [1, 0.8, 0.6], [0.8, 1, 0.4], [0.6, 0.4, 1]])\n",
495 | "b = np.matrix([[1,2,3]]).T # Note o transposto precisamos de um vetor coluna\n",
496 | "lp.solve(A,b)"
497 | ]
498 | },
499 | {
500 | "cell_type": "markdown",
501 | "metadata": {},
502 | "source": [
503 | "## Distribuições de probabilidade\n",
504 | "\n",
505 | "As principais distribuições de probabilidade estão implementadas na biblioteca `scipy.stats`. Todas as distribuições implementadas nesta biblioteca tem um conjunto rico de métodos os principais são:\n",
506 | "\n",
507 | " - pdf: função densidade probabilidade ou função de probabilidade.\n",
508 | " - cdf: função de distribuição acumulada.\n",
509 | " - sf: função de sobreviência (complementar da cdf).\n",
510 | " - ppf: função quantil (inversa da cdf).\n",
511 | " - isf: inversa da função de sobreviência (complementar do inverso da cdf).\n",
512 | " - stats: esperança, variância, assimetria (skew) e curtose.\n",
513 | " - moment: Momentos não centrais.\n",
514 | " - rvs: amostras aleatórias.\n",
515 | "\n",
516 | "Interessante notar que funções como a pdf e cdf são definidas na reta real, mesmo que a distribuição não corresponda a este suporte. Neste caso as funções vão retornar zero no caso da pdf e 0 ou 1 no caso da cdf. Por exemplo, o suporta da distribuição beta é o intervalo aberto (0,1). Assim, se a pdf fora deste intervalo será 0 e a cdf abaixo de 0 será 0 e acima de 1 será 1. \n",
517 | "\n",
518 | "Outro aspecto interessante da forma como a biblioteca `scipy.stats` implementa as distribuições é que você pode usá-las de duas formas: a primeira é a chamada forma congelada onde você inicializa a distribuição com os parâmetros de interesse e depois usa. A segunda você aplica a função diretamente passando como argumentos o ponto e os parâmetros para a avaliação da função. Vamos ver um exemplo,"
519 | ]
520 | },
521 | {
522 | "cell_type": "code",
523 | "execution_count": 20,
524 | "metadata": {},
525 | "outputs": [
526 | {
527 | "name": "stdout",
528 | "output_type": "stream",
529 | "text": [
530 | "0.0880163316911\n",
531 | "0.0880163316911\n"
532 | ]
533 | }
534 | ],
535 | "source": [
536 | "import scipy.stats as sp\n",
537 | "\n",
538 | "print(sp.norm.pdf(5, 3, 4)) # Avalia a distribuição Normal com mu = 3 e sigma2 = 4 no ponto 5.\n",
539 | "\n",
540 | "mydist = sp.norm(3, 4) # Modo frozen \n",
541 | "print(mydist.pdf(5))"
542 | ]
543 | },
544 | {
545 | "cell_type": "markdown",
546 | "metadata": {},
547 | "source": [
548 | "A biblioteca `scipy.stats` é muito rica em distribuições e a documentação é muito detalhada recomendo que veja o site da biblioteca [scipy.stats](https://docs.scipy.org/doc/scipy/reference/stats.html). Um outro aspecto útil é que todas as distribuições contínuas estão implementadas como um modelo de locação e escala. Esta é uma abordagem um pouco não usual, mas uma grande vantagem é que sabemos a parametrização de todas as distribuições contínuas previamente. A lista de distribuições é muito extensa e inclui distribuições multivariadas como a Gaussiana, Dirichlet e Wishart. \n",
549 | "\n",
550 | "Como um exemplo para explorar como usamos as distribuições da `scipy.stats` vou usar em um primeiro momento a distribuição Gaussiana porque suas propriedades são bem conhecidas. Em um segundo momento fazer usar uma distribuição não usual como a *generalized extreme value distribution*. Vamos calcular algumas quantidades da distribuição Gaussiana."
551 | ]
552 | },
553 | {
554 | "cell_type": "code",
555 | "execution_count": 59,
556 | "metadata": {},
557 | "outputs": [
558 | {
559 | "name": "stdout",
560 | "output_type": "stream",
561 | "text": [
562 | "10.0 25.0 0.0 0.0\n"
563 | ]
564 | }
565 | ],
566 | "source": [
567 | "my_norm = sp.norm(loc = 10, scale = 5)\n",
568 | "# Aspectos da distribuição\n",
569 | "my_norm.expect() # Esperança\n",
570 | "my_norm.median() # Mediana\n",
571 | "my_norm.moment(n = 1) # Primeiro momento (esperança)\n",
572 | "my_norm.moment(n = 2) # Segundo momento\n",
573 | "my_norm.stats() # Média e variancia\n",
574 | "my_norm.std() # Erro padrão\n",
575 | "my_norm.var() # Variance\n",
576 | "my_norm.entropy() # Entropia\n",
577 | "\n",
578 | "mean, var, skew, kurt = my_norm.stats(moments = 'mvsk')\n",
579 | "print(mean, var, skew, kurt)"
580 | ]
581 | },
582 | {
583 | "cell_type": "markdown",
584 | "metadata": {},
585 | "source": [
586 | "Ainda não falamos sobre gráficos em python, mas eu vou inicializar uma figura, mais detalhes serão vistos nos próximos encontros. \n",
587 | "Gráfico da função densidade probabilidade."
588 | ]
589 | },
590 | {
591 | "cell_type": "code",
592 | "execution_count": 77,
593 | "metadata": {},
594 | "outputs": [
595 | {
596 | "data": {
597 | "text/plain": [
598 | "[]"
599 | ]
600 | },
601 | "execution_count": 77,
602 | "metadata": {},
603 | "output_type": "execute_result"
604 | }
605 | ],
606 | "source": [
607 | "import matplotlib.pyplot as plt\n",
608 | "fig, ax = plt.subplots(1, 1)\n",
609 | "\n",
610 | "x = np.linspace(my_norm.ppf(0.01), my_norm.ppf(0.99), 100)\n",
611 | "ax.plot(x, my_norm.pdf(x), 'r-', lw=1, alpha=0.6, label='norm pdf')"
612 | ]
613 | },
614 | {
615 | "cell_type": "markdown",
616 | "metadata": {},
617 | "source": [
618 | "Vamos simular uma amostra aleatório da distribuição Gaussiana e fazer um histograma e sobrepor a densidade que acabamos de calcular."
619 | ]
620 | },
621 | {
622 | "cell_type": "code",
623 | "execution_count": 78,
624 | "metadata": {},
625 | "outputs": [
626 | {
627 | "data": {
628 | "image/png": "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\nfWOMSSL/H/AQ+WbiQp7tAAAAAElFTkSuQmCC\n",
629 | "text/plain": [
630 | ""
631 | ]
632 | },
633 | "metadata": {},
634 | "output_type": "display_data"
635 | }
636 | ],
637 | "source": [
638 | "amostra = my_norm.rvs(10000)\n",
639 | "ax.hist(amostra, normed=True, histtype='stepfilled', alpha=0.2)\n",
640 | "ax.legend(loc='best', frameon=False)\n",
641 | "plt.show()"
642 | ]
643 | },
644 | {
645 | "cell_type": "markdown",
646 | "metadata": {},
647 | "source": [
648 | "Outro método que também está disponível para todas as distribuições implementadas na biblioteca `scipy.stats` é o método `fit`. Como o nome sugere este método ajusta a distribuição para um vetor de observações. "
649 | ]
650 | },
651 | {
652 | "cell_type": "code",
653 | "execution_count": 82,
654 | "metadata": {},
655 | "outputs": [
656 | {
657 | "name": "stdout",
658 | "output_type": "stream",
659 | "text": [
660 | "(10.482028224058263, 4.5548538593399748)\n",
661 | "(71.201643797121392, 10.459960255274375, 4.4904597272531337)\n"
662 | ]
663 | },
664 | {
665 | "data": {
666 | "text/plain": [
667 | "(9.8012505819540614, 2.6176037515189652)"
668 | ]
669 | },
670 | "execution_count": 82,
671 | "metadata": {},
672 | "output_type": "execute_result"
673 | }
674 | ],
675 | "source": [
676 | "amostra = my_norm.rvs(100)\n",
677 | "print(sp.norm.fit(amostra)) # Ajustando a própria Normal\n",
678 | "print(sp.t.fit(amostra)) # Ajustando a distribuição t\n",
679 | "print(sp.cauchy.fit(amostra)) # Cauchy ou qq outra que seja adequada."
680 | ]
681 | },
682 | {
683 | "cell_type": "markdown",
684 | "metadata": {},
685 | "source": [
686 | "Em geral as distribuições de probabilidade implementadas na biblioteca `scipy.stats` são vetorizadas. Assim, se o argumento for um objeto `ndarray` a função será aplicada em cada uma das entradas do `ndarray` e a saída também será um `ndarray`."
687 | ]
688 | },
689 | {
690 | "cell_type": "code",
691 | "execution_count": 99,
692 | "metadata": {},
693 | "outputs": [
694 | {
695 | "data": {
696 | "text/plain": [
697 | "array([ 0.00443185, 0.05399097, 0.24197072, 0.39894228, 0.24197072,\n",
698 | " 0.05399097, 0.00443185])"
699 | ]
700 | },
701 | "execution_count": 99,
702 | "metadata": {},
703 | "output_type": "execute_result"
704 | }
705 | ],
706 | "source": [
707 | "a = np.array([-3,-2,-1,0,1,2,3])\n",
708 | "sp.norm.pdf(a, loc = 0, scale = 1)"
709 | ]
710 | },
711 | {
712 | "cell_type": "markdown",
713 | "metadata": {},
714 | "source": [
715 | "Assim termino esta rápida introdução de como e onde as funções de probabilidades estão implementadas em python. Na sequência vou introduzir as principais idéias de otimização de funções em python.\n",
716 | "\n",
717 | "## Otimização\n",
718 | "\n",
719 | "Otimização de funções tem um papel central em inferência estatística. Uma vez que o estimador de maxima verossimilhança é o supremo da função de log-verossimilhança encontrar este ponto é crucial para o processo de inferência. O python através do modulo `scipy.optimization` fornece vários algoritmos para numericamente encontrar o mínimo/máximo de uma função pré-especificada. Este modulo também fornece algoritmos para solução de sistemas de equações não-lineares e minimização via métodos dos mínimos quadrados. Vamos ver alguns exemplos de como usar esta poderosa biblioteca. Como exemplo vou implementar a log-verossimilhança de um modelo de regressão linear simples."
720 | ]
721 | },
722 | {
723 | "cell_type": "code",
724 | "execution_count": 219,
725 | "metadata": {},
726 | "outputs": [
727 | {
728 | "name": "stdout",
729 | "output_type": "stream",
730 | "text": [
731 | "[ 0.955178 3.0605878 3.06253339 3.7901356 5.16958236 5.88972862\n",
732 | " 6.76677787 6.79734997 8.45627646 9.22860461]\n"
733 | ]
734 | }
735 | ],
736 | "source": [
737 | "x = np.array(range(0,10))\n",
738 | "par = np.array([2,0.8,0.5])\n",
739 | "my_norm = sp.norm(loc = 0, scale = par[2])\n",
740 | "e = my_norm.rvs(len(x))\n",
741 | "mu = par[0] + par[1]*x\n",
742 | "y = mu + e\n",
743 | "print(y)"
744 | ]
745 | },
746 | {
747 | "cell_type": "code",
748 | "execution_count": 233,
749 | "metadata": {},
750 | "outputs": [
751 | {
752 | "name": "stdout",
753 | "output_type": "stream",
754 | "text": [
755 | "[ 1.48437886 0.85184602 -0.96076513]\n",
756 | "4.58212128641\n",
757 | "[ 1.4843624 0.85184735 -0.96072641]\n",
758 | "4.582121267138361\n",
759 | "[ 1.48436238 0.85184735 -0.96072644]\n",
760 | "4.582121267138369\n",
761 | "[ 1.48462153 0.85180644 -0.96136877]\n",
762 | "4.5821260605\n",
763 | "[ -2.98023224e-07 5.96046448e-07 -5.96046448e-07]\n",
764 | "[[ 5.12949827e-02 -7.98299503e-03 5.50750805e-04]\n",
765 | " [ -7.98299503e-03 1.78946275e-03 -9.84144963e-05]\n",
766 | " [ 5.50750805e-04 -9.84144963e-05 5.10698521e-02]]\n"
767 | ]
768 | }
769 | ],
770 | "source": [
771 | "from scipy.optimize import minimize\n",
772 | "from math import exp, log\n",
773 | "\n",
774 | "def linreg(par, y, x):\n",
775 | " mu = par[0] + par[1]*x\n",
776 | " output = -sp.norm.logpdf(y, loc = mu, scale = exp(par[2])).sum()\n",
777 | " #print(output)\n",
778 | " return(output)\n",
779 | "\n",
780 | "# Avaliando a log-lik no ponto\n",
781 | "linreg(par = np.array([2.1788,0.7743, log(0.3817)]), y = y, x = x) \n",
782 | "\n",
783 | "# Valores iniciais\n",
784 | "par = np.array([2,0.8, log(2)])\n",
785 | "\n",
786 | "# Nelder-Mead\n",
787 | "res1 = minimize(linreg, par, method='nelder-mead', args = (y,x))\n",
788 | "print(res.x)\n",
789 | "print(res.fun)\n",
790 | "\n",
791 | "# Gradiente Conjugado\n",
792 | "res2 = minimize(linreg, par, method = 'CG', args = (y,x))\n",
793 | "print(res2.x)\n",
794 | "print(res2.fun)\n",
795 | "\n",
796 | "# BFGS\n",
797 | "res3 = minimize(linreg, par, method = 'BFGS', args = (y,x))\n",
798 | "print(res3.x)\n",
799 | "print(res3.fun)\n",
800 | "\n",
801 | "# Powell\n",
802 | "res4 = minimize(linreg, par, method = 'Powell', args = (y,x))\n",
803 | "print(res4.x)\n",
804 | "print(res4.fun)\n",
805 | "\n",
806 | "# Escore\n",
807 | "print(res3.jac)\n",
808 | "\n",
809 | "# Temos o inverso do hessiano\n",
810 | "print(res3.hess_inv)\n",
811 | "\n"
812 | ]
813 | }
814 | ],
815 | "metadata": {
816 | "kernelspec": {
817 | "display_name": "Python 3",
818 | "language": "python",
819 | "name": "python3"
820 | },
821 | "language_info": {
822 | "codemirror_mode": {
823 | "name": "ipython",
824 | "version": 3
825 | },
826 | "file_extension": ".py",
827 | "mimetype": "text/x-python",
828 | "name": "python",
829 | "nbconvert_exporter": "python",
830 | "pygments_lexer": "ipython3",
831 | "version": "3.5.2"
832 | }
833 | },
834 | "nbformat": 4,
835 | "nbformat_minor": 2
836 | }
837 |
--------------------------------------------------------------------------------
/aula-1-intro.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Encontro I\n",
8 | "\n",
9 | "## Objetivo\n",
10 | "\n",
11 | "O objetivo deste primeiro encontro é discutir aspectos básicos da linguagem python tais como:\n",
12 | "\n",
13 | "1. Instalação e configuração do ambiente de programação\n",
14 | " - Console python;\n",
15 | " - IPython e Spyder;\n",
16 | " - Anaconda (Jupyther notebook).\n",
17 | "2. Tipos de dados e estruturas\n",
18 | " - Tipos básicos de dados;\n",
19 | " - Operações e funções matemáticas básicas;\n",
20 | " - Estruturas básicas de dados;\n",
21 | " - Estruturas de controle;\n",
22 | " - Programação funcional;\n",
23 | " - Introdução ao NumPy;\n",
24 | "\n",
25 | "## 1. Instalação e configuração do ambiente de programação\n",
26 | "\n",
27 | "Todo sistema Linux já está equipado com uma ou geralmente duas versões da linguagem python. As versões mais comuns são a pyhton2.7 e a python3. Para iniciar o python no seu Linux basta abrir um terminal (CTRL + ALT + T) e digitar python. Caso queira verificar quais versões você tem instalado basta digitar python seguido da tecla TAB. Apesar de bastante simples esta forma de usar o python é pouco eficiente e uma série de ferramentas para auxiliar na produtividade e também no aprendizado da linguagem estão disponíveis.\n",
28 | "\n",
29 | "Neste primeiro contato com a linguagem vamos discutir outras duas formas de começar a programar em python. \n",
30 | "O programa [IPython](https://ipython.org/) é um poderoso prompt de comando para computação interativa desenvolvido para a linguagem python. IPython oferece suporte para visualização de dados interativa, sintaxe shell, tab completion e permite arquivar o histórico de código. Atualmente o projeto IPython cresceu e tornou-se um sistema multi linguagens fornecendo suporte para linguagens como Julia, R entre outras.\n",
31 | "\n",
32 | "Frequentemente o console IPython é usado em conjunto com o ambiente para desenvolvimento de computação ciêntífica [Spyder](https://pythonhosted.org/spyder/). O workflow é simples, o código python é escrito no editor Spyder e executado através do console IPython. O editor Spyder fornece recursos de edição avançados, testes interativos, debugging e introspection features. Este sistema parece mais adequado para o desenvolvimento de novos modulos e analises extensas.\n",
33 | "\n",
34 | "Dentro do escopo de data science a ferramenta [Jupyter](http://jupyter.org/) é muito popular. Jupyter notebook é uma aplicação web open-source que permite criar e compartilhar documentos que contêm código, equações, visualização e textos explicativos. Aplicações em geral envolvem, data cleaning e transformation, simulações numéricas, modelagem estatística, visualização de dados, machine learning e muito mais.\n",
35 | "\n",
36 | "Apesar de ser possível instalar cada uma das ferramentas mencionadas individualmente, uma forma mais simples de preparar o ambiente de programação python é instalar o pacote [Anaconda](https://anaconda.org/). Anaconda é uma distribuição open-source das linguagens python e R para processamento de dados em larga escala, predictive analytics e computação ciêntífica que objetiva simplificar o gerenciamento e desenvolvimento de pacotes. As versões dos pacotes são gerenciadas pelo sistema de gerenciamento de pacotes conda.\n",
37 | "\n",
38 | "Instalar o pacote Anaconda em distribuições Linux é muito fácil atráves da linha de comando do Linux. Basta seguir os seguintes passos:\n",
39 | "\n",
40 | " - Faça o download da versão Anaconda que deseja instalar. Neste exemplo vou usar a última versão (12/01/2018) disponível no endereço https://repo.continuum.io/archive/. Você também deve escolher entre a versão 2 ou 3 do python.\n",
41 | " Neste exemplo eu vou instalar a versão 3 para um computador 64 bits. Para fazer o download direto da linha de comando Linux vou usar o comando `wget`. Recomendo que faça todas essas operações no seu diretório `\\home`.\n",
42 | " \n",
43 | "```\n",
44 | "wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh\n",
45 | "\n",
46 | "```\n",
47 | " - Rode o script .sh para a instalação do Anaconda e siga as instruções. Na dúvida use a configuração default. Esse comando vai criar uma pasta chamada anaconda no diretório onde você está rodando a instalação.\n",
48 | " \n",
49 | "```\n",
50 | "bash Anaconda2-4.2.0-Linux-x86_64.sh -b -p ~/anaconda\n",
51 | "```\n",
52 | "\n",
53 | " - Precisamos colocar o Anaconda no caminho de busca para fácil acesso via a linha de comando Linux. Para isso incluímos o diretório do Anaconda em nosso arquivo `.bashrc`.\n",
54 | " \n",
55 | "```\n",
56 | "echo 'export PATH=\"~/anaconda/bin:$PATH\"' >> ~/.bashrc \n",
57 | "\n",
58 | "```\n",
59 | "\n",
60 | " - Finalmente, atualizamos o arquivo `.bashrc` e abrimos a aplicação Anaconda\n",
61 | " \n",
62 | "```\n",
63 | "source .bashrc\n",
64 | "anaconda-navigator\n",
65 | "\n",
66 | "```\n",
67 | "\n",
68 | " - Podemos atualizar todos os pacotes do Anaconda via o gerenciador de pacotes conda.\n",
69 | "\n",
70 | "```\n",
71 | "conda update conda\n",
72 | "\n",
73 | "```\n",
74 | "\n",
75 | "Assim, terminamos o processo de instalação do pacote Anaconda e estamos prontos para começar a programar em python. \n",
76 | "As instruções acima foram obtidas através do website (https://medium.com/@GalarnykMichael/install-python-on-ubuntu-anaconda-65623042cb5a).\n",
77 | "\n",
78 | "## 2. Tipos de dados e estruturas\n",
79 | "\n",
80 | "### Tipos básicos de dados\n",
81 | "\n",
82 | "A linguagem python é dinamicamente tipificada, isso significa que o interpretador do python vai reconhecer o tipo de objeto que o usuário esta declarando automaticamente. Os tipos de objetos fundamentais em python são: `integer`, `floats` e `string`.\n",
83 | "\n",
84 | "Para identificar o tipo de objeto em python usamos a comando `type()` e para imprimir o resultado de uma linha de código usamos o comando `print()` veja a seguir."
85 | ]
86 | },
87 | {
88 | "cell_type": "code",
89 | "execution_count": 1,
90 | "metadata": {},
91 | "outputs": [
92 | {
93 | "name": "stdout",
94 | "output_type": "stream",
95 | "text": [
96 | "\n",
97 | "\n",
98 | "\n",
99 | "\n"
100 | ]
101 | }
102 | ],
103 | "source": [
104 | "a1 = 10 # Definimos a1 como o integer 10\n",
105 | "print(type(a1))\n",
106 | "\n",
107 | "a2 = 3 # Definimos a2 como o integer 3\n",
108 | "print(type(a2))\n",
109 | "\n",
110 | "a3 = 10.0 # Definimos a3 como o float 10.0\n",
111 | "print(type(a3))\n",
112 | "\n",
113 | "a4 = 3.0 # Definimos a4 como o float 3.0\n",
114 | "print(type(a4))"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {},
120 | "source": [
121 | "No python 3 a divisão de integer por integer já é automaticamente tipificada para float. \n",
122 | "Entretando, em versões mais antigas (python 2.7) essa conversão não é automática e requer o uso de pacotes específicos.\n",
123 | "Neste documento estamos usando a versão 3.6.2, então não precisamos nos preocupar com isso."
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": 2,
129 | "metadata": {},
130 | "outputs": [
131 | {
132 | "name": "stdout",
133 | "output_type": "stream",
134 | "text": [
135 | "3.3333333333333335\n",
136 | "\n",
137 | "3.3333333333333335\n",
138 | "\n",
139 | "3.3333333333333335\n",
140 | "\n"
141 | ]
142 | }
143 | ],
144 | "source": [
145 | "b1 = a1/a2 # Divisão integer por integer -> float\n",
146 | "print(b1)\n",
147 | "print(type(b1)) \n",
148 | "\n",
149 | "b2 = a3/a4 # Divisão float por float -> float\n",
150 | "print(b2)\n",
151 | "print(type(b2))\n",
152 | "\n",
153 | "b3 = a1/a4 # Divisão integer por float -> float\n",
154 | "print(b3)\n",
155 | "print(type(b3))"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "Um aspecto muito interessante da linguagem python é que todos os objetos tem uma classe e toda classe tem uma série de atributos associados. Por exemplo, podemos acessar o número de bits usados pelo integer 10."
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "execution_count": 3,
168 | "metadata": {},
169 | "outputs": [
170 | {
171 | "data": {
172 | "text/plain": [
173 | "4"
174 | ]
175 | },
176 | "execution_count": 3,
177 | "metadata": {},
178 | "output_type": "execute_result"
179 | }
180 | ],
181 | "source": [
182 | "a1.bit_length()"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {},
188 | "source": [
189 | "Entretanto, objetos do tipo float obviamente não tem esse atributo. Você pode obter informações sobre float objetos usando o modulo `sys`."
190 | ]
191 | },
192 | {
193 | "cell_type": "code",
194 | "execution_count": 4,
195 | "metadata": {},
196 | "outputs": [
197 | {
198 | "data": {
199 | "text/plain": [
200 | "sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)"
201 | ]
202 | },
203 | "execution_count": 4,
204 | "metadata": {},
205 | "output_type": "execute_result"
206 | }
207 | ],
208 | "source": [
209 | "import sys \n",
210 | "sys.float_info"
211 | ]
212 | },
213 | {
214 | "cell_type": "markdown",
215 | "metadata": {},
216 | "source": [
217 | "Internamente um float é representado como a razão entre dois integers. Para ver isso, objetos da class float tem um atributo."
218 | ]
219 | },
220 | {
221 | "cell_type": "code",
222 | "execution_count": 5,
223 | "metadata": {},
224 | "outputs": [
225 | {
226 | "name": "stdout",
227 | "output_type": "stream",
228 | "text": [
229 | "(10, 1)\n",
230 | "(3152519739159347, 9007199254740992)\n"
231 | ]
232 | }
233 | ],
234 | "source": [
235 | "print(a3.as_integer_ratio())\n",
236 | "c1 = 0.35\n",
237 | "print(c1.as_integer_ratio())"
238 | ]
239 | },
240 | {
241 | "cell_type": "markdown",
242 | "metadata": {},
243 | "source": [
244 | "O último tipo básico de dado que veremos é o `strings`. `strings` em geral são usadas para representar textos os nomes e o python tem um rico ambiente para trabalhar com strings. Veja os exemplos abaixo"
245 | ]
246 | },
247 | {
248 | "cell_type": "code",
249 | "execution_count": 6,
250 | "metadata": {},
251 | "outputs": [
252 | {
253 | "name": "stdout",
254 | "output_type": "stream",
255 | "text": [
256 | "\n"
257 | ]
258 | }
259 | ],
260 | "source": [
261 | "t = \"isto é um objeto string\"\n",
262 | "print(type(t))"
263 | ]
264 | },
265 | {
266 | "cell_type": "markdown",
267 | "metadata": {},
268 | "source": [
269 | "Objetos do tipo `str` tem um grande conjunto de atributos."
270 | ]
271 | },
272 | {
273 | "cell_type": "code",
274 | "execution_count": 7,
275 | "metadata": {},
276 | "outputs": [
277 | {
278 | "name": "stdout",
279 | "output_type": "stream",
280 | "text": [
281 | "Isto é um objeto string\n",
282 | "['isto', 'é', 'um', 'objeto', 'string']\n",
283 | "17\n",
284 | "isto|é|um|objeto|string\n",
285 | "o é um objeto \n",
286 | "3\n",
287 | "ISTO É UM OBJETO STRING\n",
288 | "isto é um objeto string\n"
289 | ]
290 | },
291 | {
292 | "data": {
293 | "text/plain": [
294 | "'m|i|n|h|a| |s|e|g|u|n|d|a| |s|t|r|i|n|g'"
295 | ]
296 | },
297 | "execution_count": 7,
298 | "metadata": {},
299 | "output_type": "execute_result"
300 | }
301 | ],
302 | "source": [
303 | "print(t.capitalize()) # capitaliza a primeira letra\n",
304 | "print(t.split()) # corta por palavras\n",
305 | "print(t.find('string')) # index da primeira letra onde a palavra string começa\n",
306 | "print(t.replace(\" \", \"|\")) # troca espaço em branco por |\n",
307 | "print(t.strip('string')) # Remove uma palavra e/ou conjunto de strings\n",
308 | "print(t.count('o')) # Conta a ocorrência de uma string\n",
309 | "print(t.upper())\n",
310 | "print(t.lower())\n",
311 | "t2 = \"minha segunda string\"\n",
312 | "\"|\".join(t2) # Concatena strings\n"
313 | ]
314 | },
315 | {
316 | "cell_type": "markdown",
317 | "metadata": {},
318 | "source": [
319 | "Uma ferramenta muito poderosa quando trabalhando com strings é expressões regulares. Python oferece tais funcionalidades no modulo `re`."
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": 8,
325 | "metadata": {
326 | "collapsed": true
327 | },
328 | "outputs": [],
329 | "source": [
330 | "import re"
331 | ]
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "metadata": {},
336 | "source": [
337 | "Suponha que temos um grande conjunto de dados que contêm uma série temporal e a respectiva informação de data e hora. Em geral, a informação da data aparece em um formato que o python não reconhece naturalmente. Entretanto, a informação pode geralmente ser descrita por uma expressão regular. Considere o seguinte objeto string"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": 9,
343 | "metadata": {},
344 | "outputs": [
345 | {
346 | "name": "stdout",
347 | "output_type": "stream",
348 | "text": [
349 | "\n",
350 | "'01/18/2014 13:00:00', 100, '1st';\n",
351 | "'01/18/2014 13:30:00', 110, '2nd';\n",
352 | "'01/18/2014 14:00:00', 120, '3rd';\n",
353 | "\n",
354 | "[\"'01/18/2014 13:00:00'\", \"'01/18/2014 13:30:00'\", \"'01/18/2014 14:00:00'\"]\n"
355 | ]
356 | }
357 | ],
358 | "source": [
359 | "series = \"\"\"\n",
360 | "'01/18/2014 13:00:00', 100, '1st';\n",
361 | "'01/18/2014 13:30:00', 110, '2nd';\n",
362 | "'01/18/2014 14:00:00', 120, '3rd';\n",
363 | "\"\"\"\n",
364 | "print(series)\n",
365 | "\n",
366 | "dt = re.compile(\"'[0-9/:\\s]+'\")\n",
367 | "result = dt.findall(series)\n",
368 | "print(result)"
369 | ]
370 | },
371 | {
372 | "cell_type": "markdown",
373 | "metadata": {},
374 | "source": [
375 | "A string resultante pode ser convertida para objetos do tipo `datetime`."
376 | ]
377 | },
378 | {
379 | "cell_type": "code",
380 | "execution_count": 10,
381 | "metadata": {},
382 | "outputs": [
383 | {
384 | "name": "stdout",
385 | "output_type": "stream",
386 | "text": [
387 | "2014-01-18 13:00:00\n",
388 | "\n"
389 | ]
390 | }
391 | ],
392 | "source": [
393 | "from datetime import datetime\n",
394 | "pydt = datetime.strptime(result[0].replace(\"'\",\"\"), '%m/%d/%Y %H:%M:%S')\n",
395 | "print(pydt)\n",
396 | "print(type(pydt))"
397 | ]
398 | },
399 | {
400 | "cell_type": "markdown",
401 | "metadata": {},
402 | "source": [
403 | "Com isso terminamos nossa discusão sobre tipos básicos de dados em python."
404 | ]
405 | },
406 | {
407 | "cell_type": "markdown",
408 | "metadata": {},
409 | "source": [
410 | "### Operações e funções matemáticas básicas\n",
411 | "\n",
412 | "\n",
413 | "Em termos de operações matemáticas simples (soma, subtração, multiplicação e divisão) o python funciona exatamente como uma simples calculadora."
414 | ]
415 | },
416 | {
417 | "cell_type": "code",
418 | "execution_count": 11,
419 | "metadata": {},
420 | "outputs": [
421 | {
422 | "name": "stdout",
423 | "output_type": "stream",
424 | "text": [
425 | "30\n",
426 | "\n",
427 | "30.0\n",
428 | "\n",
429 | "-10\n",
430 | "\n",
431 | "-10.0\n",
432 | "\n",
433 | "1480.0\n",
434 | "1480.0\n"
435 | ]
436 | }
437 | ],
438 | "source": [
439 | "c1 = 10 + 20 # Soma de integer\n",
440 | "print(c1)\n",
441 | "print(type(c1))\n",
442 | "\n",
443 | "c2 = 10.0 + 20.0 # Soma de float\n",
444 | "print(c2)\n",
445 | "print(type(c2))\n",
446 | "\n",
447 | "c3 = 10 - 20 # Subtração de integer\n",
448 | "print(c3)\n",
449 | "print(type(c3))\n",
450 | "\n",
451 | "c4 = 10.0 - 20.0 # Subtração de float\n",
452 | "print(c4)\n",
453 | "print(type(c4))\n",
454 | "\n",
455 | "c5 = 30*50 + 80/4 - 20*2 # python respeita as operações matemáticas naturais mesmo sem o uso de parenteses.\n",
456 | "print(c5)\n",
457 | "\n",
458 | "# apesar de sempre recomendar o uso dos parenteses para facilitar a leitura de grandes equações\n",
459 | "c6 = (30*50) + (80/4) - (20*2) \n",
460 | "print(c6)"
461 | ]
462 | },
463 | {
464 | "cell_type": "markdown",
465 | "metadata": {},
466 | "source": [
467 | "Funções matemáticas especiais como logaritmo, exponencial, potênciação, funções trigonométricas, radiciação entre outras estão disponíveis através do modulo `math`. Ao carregar um modulo em python recomenda-se que apenas as funções que serão usadas sejam carregadas. Por exemplo, no código abaixo queremos calcular o logaritmo, a raiz quadrada, a exponencial e a potência de um número. Desta forma, importamos apenas estas funções do modulo `math`. Uma lista com todas as funções matemáticas disponíveis no modulo `math` pode ser encontrada no endereço (https://www.programiz.com/python-programming/modules/math). "
468 | ]
469 | },
470 | {
471 | "cell_type": "code",
472 | "execution_count": 12,
473 | "metadata": {},
474 | "outputs": [
475 | {
476 | "name": "stdout",
477 | "output_type": "stream",
478 | "text": [
479 | "2.302585092994046\n",
480 | "3.1622776601683795\n",
481 | "1.0\n",
482 | "100.0\n",
483 | "1000.0\n"
484 | ]
485 | }
486 | ],
487 | "source": [
488 | "from math import log, sqrt, exp, pow\n",
489 | "\n",
490 | "print(log(10)) # Logaritmo de 10\n",
491 | "print(sqrt(10)) # raiz quadrada de 10\n",
492 | "print(exp(0)) # exponencial\n",
493 | "print(pow(10, 2)) # 10^2\n",
494 | "print(pow(10, 3)) # 10^3\n"
495 | ]
496 | },
497 | {
498 | "cell_type": "markdown",
499 | "metadata": {},
500 | "source": [
501 | "### Estruturas básicas de dados\n",
502 | "\n",
503 | "Como uma regra geral, estruturas de dados são objetos que contêm possívelmente um grande número de outros objetos. Entre outros o python oferece as seguintes estruturas de dados:\n",
504 | "\n",
505 | " - `tuple`: Coleção arbitrária de objetos com poucos métodos disponíveis.\n",
506 | " - `list`: Coleção arbitrária de objetos com muitos métodos disponíveis.\n",
507 | " - `dict`: Objeto que armazenam valores-chaves.\n",
508 | " - `set`: Coleção não enumerada de objetos para outros objetos únicos.\n",
509 | "\n",
510 | "#### Tuples\n",
511 | "\n",
512 | "`tuple` é uma estrutura muito simples e com poucos recursos. A `tuple` é definida através de um conjunto de objetos entre parêntenses."
513 | ]
514 | },
515 | {
516 | "cell_type": "code",
517 | "execution_count": 13,
518 | "metadata": {},
519 | "outputs": [
520 | {
521 | "name": "stdout",
522 | "output_type": "stream",
523 | "text": [
524 | "\n"
525 | ]
526 | }
527 | ],
528 | "source": [
529 | "t1 = (1, 2.5, 'tuple')\n",
530 | "print(type(t1))"
531 | ]
532 | },
533 | {
534 | "cell_type": "markdown",
535 | "metadata": {},
536 | "source": [
537 | "Podemos selecionar elementos de uma `tuple` através de seus indices. \n",
538 | "Um aspecto importante é que o python usa zero-based numbering, ou seja, os índices começam em zero.\n",
539 | "Também podemos selecionar slices da `tuple` através de seus índices."
540 | ]
541 | },
542 | {
543 | "cell_type": "code",
544 | "execution_count": 14,
545 | "metadata": {},
546 | "outputs": [
547 | {
548 | "name": "stdout",
549 | "output_type": "stream",
550 | "text": [
551 | "2.5\n",
552 | "1\n",
553 | "\n",
554 | "(1,)\n",
555 | "(1, 2.5)\n",
556 | "tuple\n"
557 | ]
558 | }
559 | ],
560 | "source": [
561 | "print(t1[1])\n",
562 | "print(t1[0])\n",
563 | "print(type(t1[2]))\n",
564 | "\n",
565 | "print(t1[0:1]) # Seleciona apenas o elemento na posição 0\n",
566 | "print(t1[0:2]) # Elemento da posição 0 e 1\n",
567 | "print(t1[-1]) # Índices negativos tbm funcionam"
568 | ]
569 | },
570 | {
571 | "cell_type": "markdown",
572 | "metadata": {},
573 | "source": [
574 | "Para objetos do tipo `tuple` existem apenas dois métodos disponíveis: `count` e `index`. O método `count` conta as ocorrências de um certo valor e o método `index` retorno o índice que o valor apareceu pela primeira vez."
575 | ]
576 | },
577 | {
578 | "cell_type": "code",
579 | "execution_count": 15,
580 | "metadata": {},
581 | "outputs": [
582 | {
583 | "name": "stdout",
584 | "output_type": "stream",
585 | "text": [
586 | "4\n",
587 | "7\n"
588 | ]
589 | }
590 | ],
591 | "source": [
592 | "t2 = (1,2,2,2,3,3,3,5,5,5,5, \"tuple2\")\n",
593 | "print(t2.count(5))\n",
594 | "print(t2.index(5))"
595 | ]
596 | },
597 | {
598 | "cell_type": "markdown",
599 | "metadata": {},
600 | "source": [
601 | "#### Lists\n",
602 | "\n",
603 | "Objetos do tipo `list` são muito mais flexíveis e poderosos do que `tuple`. Uma `list` é definida através de colchetes (brackets) e em termos de aplicações em estatística serão muito úteis. Entretando, a seleção de elementos e comportamentos básicas são similares aos de uma `tuple`."
604 | ]
605 | },
606 | {
607 | "cell_type": "code",
608 | "execution_count": 16,
609 | "metadata": {},
610 | "outputs": [
611 | {
612 | "name": "stdout",
613 | "output_type": "stream",
614 | "text": [
615 | "\n",
616 | "lista\n"
617 | ]
618 | }
619 | ],
620 | "source": [
621 | "l1 = [1, 2.5, 'lista']\n",
622 | "print(type(l1))\n",
623 | "print(l1[2]) # Elemento posição 3"
624 | ]
625 | },
626 | {
627 | "cell_type": "markdown",
628 | "metadata": {},
629 | "source": [
630 | "Podemos também converter objetos do tipo `tuple` para `list` usando a função `list()`."
631 | ]
632 | },
633 | {
634 | "cell_type": "code",
635 | "execution_count": 17,
636 | "metadata": {},
637 | "outputs": [
638 | {
639 | "name": "stdout",
640 | "output_type": "stream",
641 | "text": [
642 | "\n",
643 | "\n"
644 | ]
645 | }
646 | ],
647 | "source": [
648 | "t1 = (1, 2.5, 'tuple')\n",
649 | "print(type(t1))\n",
650 | "t1 = list(t1)\n",
651 | "print(type(t1))"
652 | ]
653 | },
654 | {
655 | "cell_type": "markdown",
656 | "metadata": {},
657 | "source": [
658 | "Objetos do tipo `list` podem ser expandidos e/ou reducidos. Em python essas propriedades definem um objeto `mutable`. Assim, temos que um `list` é `mutable` enquanto que um `tuple` é `immutable`. Vamos ver algumas operações com objetos `list`."
659 | ]
660 | },
661 | {
662 | "cell_type": "code",
663 | "execution_count": 18,
664 | "metadata": {},
665 | "outputs": [
666 | {
667 | "name": "stdout",
668 | "output_type": "stream",
669 | "text": [
670 | "[1, 2.5, 'lista', [4, 3]]\n",
671 | "[1, 2.5, 'lista', [4, 3], 1.0, 1.5, 2.0]\n",
672 | "[1, 'insert', 2.5, 'lista', [4, 3], 1.0, 1.5, 2.0]\n",
673 | "[1, 'insert', 2.5, [4, 3], 1.0, 1.5, 2.0]\n",
674 | "[1, 'insert', 2.5, 1.0, 1.5, 2.0]\n",
675 | "[4, 3]\n"
676 | ]
677 | }
678 | ],
679 | "source": [
680 | "# Acrescenta valores ao fim da list\n",
681 | "l1.append([4, 3])\n",
682 | "print(l1)\n",
683 | "# Extende a list ja existente\n",
684 | "l1.extend([1.0, 1.5, 2.0])\n",
685 | "print(l1)\n",
686 | "# Insere objetos em uma posição especifica\n",
687 | "l1.insert(1, 'insert')\n",
688 | "print(l1)\n",
689 | "# Remove a primeira occorência de um objeto\n",
690 | "l1.remove('lista')\n",
691 | "print(l1)\n",
692 | "# Remove e retorna o objeto em um indice\n",
693 | "p = l1.pop(3)\n",
694 | "print(l1)\n",
695 | "print(p)\n"
696 | ]
697 | },
698 | {
699 | "cell_type": "markdown",
700 | "metadata": {},
701 | "source": [
702 | "Slicing refere-se a operação de quebrar o conjunto de dados em pequenas partes de interesse."
703 | ]
704 | },
705 | {
706 | "cell_type": "code",
707 | "execution_count": 19,
708 | "metadata": {},
709 | "outputs": [
710 | {
711 | "data": {
712 | "text/plain": [
713 | "[2.5, 1.0, 1.5]"
714 | ]
715 | },
716 | "execution_count": 19,
717 | "metadata": {},
718 | "output_type": "execute_result"
719 | }
720 | ],
721 | "source": [
722 | "l1[2:5] # Elementos da terceira a quinta posição"
723 | ]
724 | },
725 | {
726 | "cell_type": "markdown",
727 | "metadata": {},
728 | "source": [
729 | "Mais alguns exemplos de operações com objetos `list`."
730 | ]
731 | },
732 | {
733 | "cell_type": "code",
734 | "execution_count": 20,
735 | "metadata": {},
736 | "outputs": [
737 | {
738 | "name": "stdout",
739 | "output_type": "stream",
740 | "text": [
741 | "[1, 'insert', 2.5, 1.0, 1.5, 2.0]\n",
742 | "[1, 'insert', 5, 1.0, 1.5, 2.0]\n",
743 | "[1, 'insert', 5, 2, 1, 3, 2.0]\n",
744 | "1\n",
745 | "[1, 'insert', 5, 3, 2.0, 10]\n",
746 | "[1, 'insert', 5, 3, 2.0, 10, 10, 20, 30]\n",
747 | "[30, 20, 10, 10, 2.0, 3, 5, 'insert', 1]\n"
748 | ]
749 | },
750 | {
751 | "ename": "TypeError",
752 | "evalue": "'<' not supported between instances of 'str' and 'int'",
753 | "output_type": "error",
754 | "traceback": [
755 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
756 | "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
757 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0ml1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreverse\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Do maior para o menor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ml1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0ml1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msort\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Do menor para o maior\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ml1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
758 | "\u001b[0;31mTypeError\u001b[0m: '<' not supported between instances of 'str' and 'int'"
759 | ]
760 | }
761 | ],
762 | "source": [
763 | "print(l1)\n",
764 | "l1[2] = 5 # substitui o elemento 3 pelo valor 5\n",
765 | "print(l1)\n",
766 | "l1[3:5] = [2,1,3] # Interessante\n",
767 | "print(l1)\n",
768 | "l1.append(10) # Junta o 10 na list\n",
769 | "print(l1.count(10)) # Conta o numero de ocorrência do 10\n",
770 | "del l1[3:5] # Deleta\n",
771 | "print(l1)\n",
772 | "l1.extend([10,20,30])\n",
773 | "print(l1)\n",
774 | "l1.reverse() # Do maior para o menor\n",
775 | "print(l1)\n",
776 | "l1.sort() # Do menor para o maior\n",
777 | "print(l1)"
778 | ]
779 | },
780 | {
781 | "cell_type": "markdown",
782 | "metadata": {},
783 | "source": [
784 | "#### Dicts\n",
785 | "\n",
786 | "Objetos do tipo `dict` são dicionários `mutable` e permitem o armazenamento de dados através de `keys` que podem ser por exemplo, `string`. `dict` objetos não são ordenáveis. Um exemplo ilustra melhor a diferença entre `list` e `dict`."
787 | ]
788 | },
789 | {
790 | "cell_type": "code",
791 | "execution_count": null,
792 | "metadata": {},
793 | "outputs": [],
794 | "source": [
795 | "d = {\n",
796 | " 'Nome' : 'Wagner Hugo Bonat',\n",
797 | " 'País' : 'Brasil',\n",
798 | " 'Profissão' : 'Professor',\n",
799 | " 'Idade' : 32\n",
800 | "}\n",
801 | "print(type(d))\n",
802 | "print( d['Nome'], d['Idade'] )\n",
803 | "\n",
804 | "d.keys() # Acessa o nome das chaves\n",
805 | "\n",
806 | "d.values() # Acessa os valores"
807 | ]
808 | },
809 | {
810 | "cell_type": "markdown",
811 | "metadata": {},
812 | "source": [
813 | "Existem uma séries de métodos para iterar em objetos da classe `dict`. Veremos detalhes na seção de estruturas de controle e programação funcional."
814 | ]
815 | },
816 | {
817 | "cell_type": "markdown",
818 | "metadata": {},
819 | "source": [
820 | "#### Sets\n",
821 | "\n",
822 | "A última estrutura de dados básica que vamos discutir é a estrutura `set`. A estrutura `set` implementa a teoria dos conjuntos atráves de simples objetos. Ela pode ser útil para explicar conceitos de probabilidade. Vamos ver alguns conceitos simples de probabilidade usando a estrutura `set`em python."
823 | ]
824 | },
825 | {
826 | "cell_type": "code",
827 | "execution_count": null,
828 | "metadata": {},
829 | "outputs": [],
830 | "source": [
831 | "s = set(['A','B', 'AB', 'BA', 'B', 'BA']) # Note que objeto repetidas são automaticamente descartados\n",
832 | "print(s)\n",
833 | "t = set(['B', 'BB', 'AA', 'A'])\n",
834 | "print(t)\n",
835 | "\n",
836 | "print(s.union(t)) # União dos conjuntos\n",
837 | "print(s.intersection(t)) # Intersecção\n",
838 | "print(s.difference(t)) # Em s mas não em t\n",
839 | "print(t.difference(s)) # Em t mas não em s\n",
840 | "print(s.symmetric_difference(t)) # em s ou t mas não em ambos\n"
841 | ]
842 | },
843 | {
844 | "cell_type": "markdown",
845 | "metadata": {},
846 | "source": [
847 | "### Estruturas de controle\n",
848 | "\n",
849 | "Estruturas de controle são a forma que o programador tem de controlar o que e para quais objetos o código vai funcionar. Apesar de uso geral, nesta seção vou focar mais em objetos do tipo `list`. \n",
850 | "O exemplo a seguir define uma lista com 6 valores e imprime o quadrado os valores entre os índices 2 e 5. \n",
851 | "Em python a indentação é parte da linguagem, então observe com atenção os espaços em branco na segunda linha.\n",
852 | "Note ainda que no segundo loop for o índice teve que ser apropriadamente restrito.\n",
853 | "Esta estrutura de looping é muito útil e fácil de usar. "
854 | ]
855 | },
856 | {
857 | "cell_type": "code",
858 | "execution_count": null,
859 | "metadata": {},
860 | "outputs": [],
861 | "source": [
862 | "l2 = [1,2,3,4,5,6]\n",
863 | "print(l2[2:5])\n",
864 | "\n",
865 | "for i in l2[2:5]:\n",
866 | " print(l2[i] ** 2)\n",
867 | "\n",
868 | "for i in l2:\n",
869 | " print(l2[i-1])"
870 | ]
871 | },
872 | {
873 | "cell_type": "markdown",
874 | "metadata": {},
875 | "source": [
876 | "Entretando, podemos usar o mais tradicional loop baseado em um contador (como usual em linguagens com C)."
877 | ]
878 | },
879 | {
880 | "cell_type": "code",
881 | "execution_count": null,
882 | "metadata": {},
883 | "outputs": [],
884 | "source": [
885 | "r = range(0, 6, 1)\n",
886 | "\n",
887 | "for r in range(2, 5):\n",
888 | " print(l2[r] ** 2)"
889 | ]
890 | },
891 | {
892 | "cell_type": "markdown",
893 | "metadata": {},
894 | "source": [
895 | "Python também oferece as típicas estruturas de controle condicional `if`, `elif` e `else`. O uso é similar a outras linguagens."
896 | ]
897 | },
898 | {
899 | "cell_type": "code",
900 | "execution_count": null,
901 | "metadata": {},
902 | "outputs": [],
903 | "source": [
904 | "for i in range(1, 10):\n",
905 | " if i % 2 == 0: # % resto da divisão \n",
906 | " print(\"%d é par\" % i)\n",
907 | " elif i % 3 == 0:\n",
908 | " print(\"%d é múltiplo de 3\" % i)\n",
909 | " else:\n",
910 | " print(\"%d é ímpar\" % i)\n",
911 | " "
912 | ]
913 | },
914 | {
915 | "cell_type": "markdown",
916 | "metadata": {},
917 | "source": [
918 | "O última estrutura de controle que vamos ver será o `while`."
919 | ]
920 | },
921 | {
922 | "cell_type": "code",
923 | "execution_count": null,
924 | "metadata": {},
925 | "outputs": [],
926 | "source": [
927 | "total = 0\n",
928 | "while total < 100:\n",
929 | " total += 1\n",
930 | "print(total)"
931 | ]
932 | },
933 | {
934 | "cell_type": "markdown",
935 | "metadata": {},
936 | "source": [
937 | "Uma especialidade do python é a chamada `list comprehensions`. Ao invés de rodar sobre objetos tipo `list` já existentes, esta abordagem gerá a `list` via loops em uma forma muito compacta."
938 | ]
939 | },
940 | {
941 | "cell_type": "code",
942 | "execution_count": null,
943 | "metadata": {},
944 | "outputs": [],
945 | "source": [
946 | "m = [i ** 2 for i in range(5)]\n",
947 | "print(m)"
948 | ]
949 | },
950 | {
951 | "cell_type": "markdown",
952 | "metadata": {},
953 | "source": [
954 | "Em certo sentido a abordagem de `list comprehensions` já fornece algo como vetorização de código, que será discutida em detalhes na seção Vetorização de código.\n",
955 | "\n",
956 | "### Programação funcional\n",
957 | "\n",
958 | "Python oferece muitas ferramentas para programação funcional *functional programming*. Programação funcional refere-se ao processo de aplicar uma função a um conjunto de entradas, em geral em python a um objeto do tipo `list`. Entre estas ferramentas estão `filter`, `map` e `reduce`. Entretando, para começar precisamos definir uma função em python. \n",
959 | "\n",
960 | "Para começar vamos implementar a distribuição de probabilidade mais usada em estatística, ou seja, a distribuição Gaussiana. A função densidade probabilidade da distribuição Gaussiana é dada por\n",
961 | "\n",
962 | "$$ f(y;\\mu, \\sigma^2) = \\frac{1}{\\sqrt{2 \\pi \\sigma^2}} \\exp\\left \\{- \\frac{1}{2\\sigma^2} (y - \\mu)^2 \\right \\}, $$\n",
963 | "onde $ y, \\mu \\in \\Re$ e $\\sigma^2 > 0$. Nesta parametrização tem-se que $E(Y) = \\mu$ e $Var(Y) = \\sigma^2$.\n",
964 | "\n",
965 | "Para implementar tal função em python, primeiro identificamos quais argumentos serão necessários. Neste caso são três $y$, $\\mu$ e $\\sigma^2$. Na sequência identificamos quais as funções matemática especiais envolvidas na função, no caso da distribuição Gaussiana temos, raiz quadrada, constant $\\pi$, potência e exponencial (`sqrt`, `pi`, `pow` e `exp`) todas estão disponíveis através do módulo `math`. Vamos ver como fica a distribuição Gaussiana implementada em python."
966 | ]
967 | },
968 | {
969 | "cell_type": "code",
970 | "execution_count": null,
971 | "metadata": {},
972 | "outputs": [],
973 | "source": [
974 | "from math import sqrt, pi, exp, pow\n",
975 | "\n",
976 | "def dnorm(y, mu = 0, sigma2 = 1):\n",
977 | " output = (1/(sqrt(2 * pi * sigma2)))*exp( - (1/(2 * sigma2)) * pow(y - mu, 2) )\n",
978 | " return output\n",
979 | "\n",
980 | "print(dnorm(y = 0))\n",
981 | "print(dnorm(y = 0, mu = 10, sigma2 = 2))"
982 | ]
983 | },
984 | {
985 | "cell_type": "markdown",
986 | "metadata": {},
987 | "source": [
988 | "Suponha que queremos aplicar a função `dnorm` para uma `list` de objetos. Podemos fazer isso usando um loop for como na seção anterior. "
989 | ]
990 | },
991 | {
992 | "cell_type": "code",
993 | "execution_count": null,
994 | "metadata": {},
995 | "outputs": [],
996 | "source": [
997 | "# Tradicional loop for\n",
998 | "numbers = [-3, -2, -1, 0, 1, 2, 3]\n",
999 | "for i in numbers:\n",
1000 | " print(dnorm(y = i, mu = 0, sigma2 = 1))"
1001 | ]
1002 | },
1003 | {
1004 | "cell_type": "markdown",
1005 | "metadata": {},
1006 | "source": [
1007 | "De uma forma mais elegante podemos usar programação funcional através da função `map` em python. "
1008 | ]
1009 | },
1010 | {
1011 | "cell_type": "code",
1012 | "execution_count": null,
1013 | "metadata": {},
1014 | "outputs": [],
1015 | "source": [
1016 | "print(list(map(dnorm, numbers)))\n",
1017 | "print(list(map(dnorm, numbers, [10,10,10,10,10,10,10], [1,1,1,1,1,1,1]))) # Um pouco incoveniente mais funciona!"
1018 | ]
1019 | },
1020 | {
1021 | "cell_type": "markdown",
1022 | "metadata": {},
1023 | "source": [
1024 | "Para funções simples (em geral de uma linha) podemos usar funções anônimas ou como são chamadas em python `lambda functions`. "
1025 | ]
1026 | },
1027 | {
1028 | "cell_type": "code",
1029 | "execution_count": null,
1030 | "metadata": {},
1031 | "outputs": [],
1032 | "source": [
1033 | "list(map(lambda x: x ** 2, numbers))"
1034 | ]
1035 | },
1036 | {
1037 | "cell_type": "markdown",
1038 | "metadata": {},
1039 | "source": [
1040 | "Funções também podem ser usadas para filtrar valores de interesse. Suponha que queremos obter apenas os valores pares de uma grande `list` de números. Primeiro definimos a função que faz a seleção e depois aplicamos ela a cada elemento da nossa lista de valores filtrando os que temos interesse."
1041 | ]
1042 | },
1043 | {
1044 | "cell_type": "code",
1045 | "execution_count": null,
1046 | "metadata": {},
1047 | "outputs": [],
1048 | "source": [
1049 | "def even(x):\n",
1050 | " return x % 2 == 0\n",
1051 | "\n",
1052 | "list(filter(even, range(15)))"
1053 | ]
1054 | },
1055 | {
1056 | "cell_type": "markdown",
1057 | "metadata": {},
1058 | "source": [
1059 | "Finalmente, podemos reduzir o conjunto de dados aplicando alguma função em todos os elementos da `list`. Um exemplo é a soma cumulativa dos objetos em uma `list`. Importante ressaltar que a função `reduce` no python 3.0 é parte do modulo functools, e portante precisa ser importada explicitamente."
1060 | ]
1061 | },
1062 | {
1063 | "cell_type": "code",
1064 | "execution_count": null,
1065 | "metadata": {},
1066 | "outputs": [],
1067 | "source": [
1068 | "from functools import reduce\n",
1069 | "\n",
1070 | "reduce(lambda x, y: x + y, range(10))"
1071 | ]
1072 | },
1073 | {
1074 | "cell_type": "markdown",
1075 | "metadata": {},
1076 | "source": [
1077 | "Podemos também usar as funções em conjunto ganhando ainda mais flexibilidade. Por exemplo, suponha que queremos somar apenas os números positivos de uma sequência de números em uma `list`."
1078 | ]
1079 | },
1080 | {
1081 | "cell_type": "code",
1082 | "execution_count": null,
1083 | "metadata": {},
1084 | "outputs": [],
1085 | "source": [
1086 | "reduce(lambda x, y: x + y, filter(even, range(20)))"
1087 | ]
1088 | },
1089 | {
1090 | "cell_type": "markdown",
1091 | "metadata": {},
1092 | "source": [
1093 | "É considerado uma boa prática evitar loop for em Python tanto quanto possível. `list comprehension` e `functional programming` atráves de funções como `map`, `filter` e `reduce` oferecem um código mais compacto e em geral de fácil leitura. \n",
1094 | "\n",
1095 | "### Estrutura de dados NumPy\n",
1096 | "\n",
1097 | "As seções anteriores mostraram que o python oferece algumas estruturas flexíveis para o armazenamento e manipulação de dados básicos. Em particular, `list` são muito úteis para trabalhar com dados e analises estatística. Entretando, quando trabalhando com analise de dados reais, tem-se a necessidade para operações de alta performance em dados com estruturas especiais. Uma das estruturas mais importantes é o `array`. `array` geralmente estruturam outros objetos em linhas e colunas. \n",
1098 | "\n",
1099 | "Assuma que estamos trabalhando com números (os conceitos funcionam também para `string`). No caso mais simples, um `array` unidimensional representa um vetor de números reais representados internamente como `float`. De forma mais geral um `array` representa uma matrix $i \\times j$ de elementos. O mais interessantes sobre `array` é que estes conceitos generalizam para cubos $i \\times j \\times k$ de elementos, bem como, para n-dimensionais arrays de corpo $i \\times j \\times k \\times l \\times, \\ldots$.\n",
1100 | "\n",
1101 | "De forma geral, matrizes são de extrema importância em estatística, assim precisamos de uma forma simples e eficiente de trabalhar ao menos com `arrays` bidimensionais. É neste ponto que a biblioteca `NumPy` é de extrema importância dentro do ambiente python.\n",
1102 | "\n",
1103 | "Antes de introduzir o modelo `NumPy` vamos discutir como `array` podem ser obtidos como uma `list` de `list`."
1104 | ]
1105 | },
1106 | {
1107 | "cell_type": "code",
1108 | "execution_count": null,
1109 | "metadata": {},
1110 | "outputs": [],
1111 | "source": [
1112 | "v = [0.5, 1, 1.5, 2, 2.5, 3] # vector of numbers\n",
1113 | "m = [v, v, v] # matriz\n",
1114 | "print(m)\n",
1115 | "m[1][0] # Segunda linha primeiro elemento"
1116 | ]
1117 | },
1118 | {
1119 | "cell_type": "markdown",
1120 | "metadata": {},
1121 | "source": [
1122 | "Podemos também ter um cubo de números, ou um `array` tridimensional."
1123 | ]
1124 | },
1125 | {
1126 | "cell_type": "code",
1127 | "execution_count": null,
1128 | "metadata": {},
1129 | "outputs": [],
1130 | "source": [
1131 | "v1 = [0.5, 1.5]\n",
1132 | "v2 = [1, 2]\n",
1133 | "m = [v1,v2]\n",
1134 | "c = [m, m]\n",
1135 | "print(c)\n",
1136 | "print(c[1])\n",
1137 | "print(c[1][0])\n",
1138 | "print(c[1][0][1])"
1139 | ]
1140 | },
1141 | {
1142 | "cell_type": "markdown",
1143 | "metadata": {},
1144 | "source": [
1145 | "É importante enfatizar que combinar elementos como feito anteriormente funciona como `reference pointers` para os objetos anteriores. Essa idéia fica clara através de um exemplo."
1146 | ]
1147 | },
1148 | {
1149 | "cell_type": "code",
1150 | "execution_count": null,
1151 | "metadata": {},
1152 | "outputs": [],
1153 | "source": [
1154 | "v = [0.5, 0.75, 1.0, 1.5, 2.0]\n",
1155 | "m = [v, v, v]\n",
1156 | "print(m)\n",
1157 | "\n",
1158 | "v[0] = 'python'\n",
1159 | "print(m)"
1160 | ]
1161 | },
1162 | {
1163 | "cell_type": "markdown",
1164 | "metadata": {},
1165 | "source": [
1166 | "Para evitar este comportamento usamos a função `deepcopy` do modulo `copy`."
1167 | ]
1168 | },
1169 | {
1170 | "cell_type": "code",
1171 | "execution_count": null,
1172 | "metadata": {},
1173 | "outputs": [],
1174 | "source": [
1175 | "from copy import deepcopy\n",
1176 | "v = [0.5, 0.75, 1.0, 1.5, 2.0]\n",
1177 | "m = 3 * [deepcopy(v), ]\n",
1178 | "print(m)\n",
1179 | "v[0] = 'python'\n",
1180 | "print(m)"
1181 | ]
1182 | },
1183 | {
1184 | "cell_type": "markdown",
1185 | "metadata": {},
1186 | "source": [
1187 | "Apesar de flexível esta forma de criar `array` não é muito útil para aplicações em estatística, uma vez que, o ferramental de álgebra linear não está disponível para este tipo de objetos. Por exemplo, a simples multiplicação de um escalar por um vetor não é definida para objetos do tipo `list` em python."
1188 | ]
1189 | },
1190 | {
1191 | "cell_type": "code",
1192 | "execution_count": null,
1193 | "metadata": {},
1194 | "outputs": [],
1195 | "source": [
1196 | "v = [0.5, 1, 1.5] # vetor\n",
1197 | "n = 2 # escalar\n",
1198 | "n*v # Repete a list duas vezes, ao invés da multiplicação de escalar por vetor"
1199 | ]
1200 | },
1201 | {
1202 | "cell_type": "markdown",
1203 | "metadata": {},
1204 | "source": [
1205 | "Isso mostra que precisamos de um tipo de objeto mais especializado que automaticamente entenda operações de álgebra linear e similares. A *library* `NumPy` traz este tipo de objeto que é chamada genericamente de `ndarray`."
1206 | ]
1207 | },
1208 | {
1209 | "cell_type": "code",
1210 | "execution_count": null,
1211 | "metadata": {},
1212 | "outputs": [],
1213 | "source": [
1214 | "import numpy as np\n",
1215 | "a = np.array([0, 0.5, 1.0, 1.5, 2.0])\n",
1216 | "print(a)\n",
1217 | "print(type(a))"
1218 | ]
1219 | },
1220 | {
1221 | "cell_type": "markdown",
1222 | "metadata": {},
1223 | "source": [
1224 | "A principal vantagem deste tipo de objeto é a grande quantidade de métodos disponíveis. Alguns exemplos,"
1225 | ]
1226 | },
1227 | {
1228 | "cell_type": "code",
1229 | "execution_count": null,
1230 | "metadata": {},
1231 | "outputs": [],
1232 | "source": [
1233 | "print(a.sum()) # Soma todos os elementos\n",
1234 | "print(a.std()) # Erro padrão\n",
1235 | "print(a.cumsum()) # Soma acumulada\n",
1236 | "print(a.shape)\n",
1237 | "print(a.size)"
1238 | ]
1239 | },
1240 | {
1241 | "cell_type": "markdown",
1242 | "metadata": {},
1243 | "source": [
1244 | "Uma lista completa de todos os métodos disponíveis para `ndarray` objetos pode ser obtida [aqui](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.html). \n",
1245 | "Do ponto de vista de aplicações em estatística a grande vantagem de objetos do tipo `ndarray` é que operações matriciais são reconhecidas. Aqui vamos apresentar apenas o básico, no decorrer da discussão teremos um encontro dedicado especificamente a álgebra linear usando `NumPy`."
1246 | ]
1247 | },
1248 | {
1249 | "cell_type": "code",
1250 | "execution_count": null,
1251 | "metadata": {},
1252 | "outputs": [],
1253 | "source": [
1254 | "a = [1, 2] # Python basic\n",
1255 | "b = [3, 4]\n",
1256 | "print(a + b) # Concatena\n",
1257 | "\n",
1258 | "a = np.array([1, 2]) # Usando NumPy\n",
1259 | "print(a*2) # Multiplicação por escalar\n",
1260 | "\n",
1261 | "b = np.array([3, 4])\n",
1262 | "print(a + b) # Soma de vetores\n",
1263 | "\n",
1264 | "# Matrix 2 x 2\n",
1265 | "c = np.matrix([ [1,2], [3,4] ])\n",
1266 | "print(c)\n",
1267 | "print(c.shape)\n",
1268 | "\n",
1269 | "c2 = np.matrix([ [4,5], [6, 7]])\n",
1270 | "print(c2[0,:]) # Primeira linha\n",
1271 | "print(c2[:,0]) # Primeira coluna\n",
1272 | "\n",
1273 | "# Multiplicacao de matrizes\n",
1274 | "np.dot(c,c2)"
1275 | ]
1276 | },
1277 | {
1278 | "cell_type": "markdown",
1279 | "metadata": {},
1280 | "source": [
1281 | "Uma outra especialidade da biblioteca `NumPy` são os `array` estruturados. Essa opção permite que em um mesmo `array` sejam armazenados diferentes tipos de dados por coluna. Porém, vamos deixar esta discussão para um encontro específico."
1282 | ]
1283 | }
1284 | ],
1285 | "metadata": {
1286 | "kernelspec": {
1287 | "display_name": "Python 3",
1288 | "language": "python",
1289 | "name": "python3"
1290 | },
1291 | "language_info": {
1292 | "codemirror_mode": {
1293 | "name": "ipython",
1294 | "version": 3
1295 | },
1296 | "file_extension": ".py",
1297 | "mimetype": "text/x-python",
1298 | "name": "python",
1299 | "nbconvert_exporter": "python",
1300 | "pygments_lexer": "ipython3",
1301 | "version": "3.5.2"
1302 | }
1303 | },
1304 | "nbformat": 4,
1305 | "nbformat_minor": 2
1306 | }
1307 |
--------------------------------------------------------------------------------