{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Manipulação de dados - III" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Agregação e agrupamento " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Agregando informações de linhas ou colunas\n", "\n", "Para agregar informações (p.ex. somar, tomar médias etc.) de linhas ou colunas podemos utilizar alguns métodos específicos já existentes em *DataFrames* e *Series*, tais como `sum`, `mean`, `cumsum` e `aggregate` (ou equivalentemente `agg`):" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "\n", "dados_covid_PB = pd.read_csv('https://superset.plataformatarget.com.br/superset/explore_json/?form_data=%7B%22slice_id%22%3A1550%7D&csv=true', \n", " sep=',', index_col=0)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/plain": [ "casosNovos 440037\n", "obitosNovos 9294\n", "dtype: int64" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_covid_PB.agg(lambda vetor: np.sum(vetor))[['casosNovos','obitosNovos']].astype('int')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos conferir esta agregação resultante com o número de casos acumulados e óbitos acumulados" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosAcumuladoscasosNovosdescartadosrecuperadosobitosAcumuladosobitosNovosLetalidade
data
2021-09-2644115513448433633375192942.00.0211
2021-09-2544102116548433133344192922.00.0211
2021-09-2444085622548430133284592903.00.0211
2021-09-2344063120348427633254092873.00.0211
2021-09-2244042829748426533195892846.00.0211
\n", "
" ], "text/plain": [ " casosAcumulados casosNovos descartados recuperados \\\n", "data \n", "2021-09-26 441155 134 484336 333751 \n", "2021-09-25 441021 165 484331 333441 \n", "2021-09-24 440856 225 484301 332845 \n", "2021-09-23 440631 203 484276 332540 \n", "2021-09-22 440428 297 484265 331958 \n", "\n", " obitosAcumulados obitosNovos Letalidade \n", "data \n", "2021-09-26 9294 2.0 0.0211 \n", "2021-09-25 9292 2.0 0.0211 \n", "2021-09-24 9290 3.0 0.0211 \n", "2021-09-23 9287 3.0 0.0211 \n", "2021-09-22 9284 6.0 0.0211 " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_covid_PB.head()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Isto também pode ser obtido utilizando o método `sum` de *DataFrames* e *Series*:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "casosNovos 440037.0\n", "obitosNovos 9294.0\n", "dtype: float64" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_covid_PB[['casosNovos','obitosNovos']].sum()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Podemos recriar a coluna `'obitosAcumulados'` com o método `cumsum` (soma cumulativa):" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "data\n", "2020-03-16 0.0\n", "2020-03-17 0.0\n", "2020-03-18 0.0\n", "2020-03-19 0.0\n", "2020-03-20 0.0\n", " ... \n", "2021-09-22 9284.0\n", "2021-09-23 9287.0\n", "2021-09-24 9290.0\n", "2021-09-25 9292.0\n", "2021-09-26 9294.0\n", "Name: obitosNovos, Length: 559, dtype: float64" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_covid_PB.obitosNovos.sort_index().cumsum()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Selecionando entradas distintas\n", "\n", "Para selecionar entradas distintas utilizamos o método `drop_duplicate`. Aqui, para exemplificar, vamos utilizar o banco de dados oficial sobre COVID no Brasil:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# pode levar um tempo para ler...\n", "covid_BR = pd.read_excel('../database/HIST_PAINEL_COVIDBR_18jul2020.xlsx')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Unnamed: 0regiaoestadomunicipiocodufcodmuncodRegiaoSaudenomeRegiaoSaudedatasemanaEpipopulacaoTCU2019casosAcumuladocasosNovosobitosAcumuladoobitosNovosRecuperadosnovosemAcompanhamentoNovosinterior/metropolitana
629803629803Centro-OesteDFBrasília53530010.053001.0DISTRITO FEDERAL2020-07-16293015268776212242103736NaNNaN1.0
629804629804Centro-OesteDFBrasília53530010.053001.0DISTRITO FEDERAL2020-07-17293015268794001779106023NaNNaN1.0
629805629805Centro-OesteDFBrasília53530010.053001.0DISTRITO FEDERAL2020-07-18293015268811631763107515NaNNaN1.0
\n", "
" ], "text/plain": [ " Unnamed: 0 regiao estado municipio coduf codmun \\\n", "629803 629803 Centro-Oeste DF Brasília 53 530010.0 \n", "629804 629804 Centro-Oeste DF Brasília 53 530010.0 \n", "629805 629805 Centro-Oeste DF Brasília 53 530010.0 \n", "\n", " codRegiaoSaude nomeRegiaoSaude data semanaEpi \\\n", "629803 53001.0 DISTRITO FEDERAL 2020-07-16 29 \n", "629804 53001.0 DISTRITO FEDERAL 2020-07-17 29 \n", "629805 53001.0 DISTRITO FEDERAL 2020-07-18 29 \n", "\n", " populacaoTCU2019 casosAcumulado casosNovos obitosAcumulado \\\n", "629803 3015268 77621 2242 1037 \n", "629804 3015268 79400 1779 1060 \n", "629805 3015268 81163 1763 1075 \n", "\n", " obitosNovos Recuperadosnovos emAcompanhamentoNovos \\\n", "629803 36 NaN NaN \n", "629804 23 NaN NaN \n", "629805 15 NaN NaN \n", "\n", " interior/metropolitana \n", "629803 1.0 \n", "629804 1.0 \n", "629805 1.0 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_BR.tail(3)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 629806 entries, 0 to 629805\n", "Data columns (total 18 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 Unnamed: 0 629806 non-null int64 \n", " 1 regiao 629806 non-null object \n", " 2 estado 629661 non-null object \n", " 3 municipio 623352 non-null object \n", " 4 coduf 629806 non-null int64 \n", " 5 codmun 625746 non-null float64\n", " 6 codRegiaoSaude 623352 non-null float64\n", " 7 nomeRegiaoSaude 623352 non-null object \n", " 8 data 629806 non-null object \n", " 9 semanaEpi 629806 non-null int64 \n", " 10 populacaoTCU2019 627412 non-null object \n", " 11 casosAcumulado 629806 non-null int64 \n", " 12 casosNovos 629806 non-null int64 \n", " 13 obitosAcumulado 629806 non-null int64 \n", " 14 obitosNovos 629806 non-null int64 \n", " 15 Recuperadosnovos 91 non-null float64\n", " 16 emAcompanhamentoNovos 91 non-null float64\n", " 17 interior/metropolitana 623352 non-null float64\n", "dtypes: float64(5), int64(7), object(6)\n", "memory usage: 86.5+ MB\n" ] } ], "source": [ "# resumo da tabela\n", "covid_BR.info()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/plain": [ "\n", "[ nan, 'RO', 'AC', 'AM', 'RR', 'PA', 'AP', 'TO', 'MA', 'PI', 'CE', 'RN', 'PB',\n", " 'PE', 'AL', 'SE', 'BA', 'MG', 'ES', 'RJ', 'SP', 'PR', 'SC', 'RS', 'MS', 'MT',\n", " 'GO', 'DF']\n", "Length: 28, dtype: object" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# todos os estados únicos\n", "covid_BR.estado.drop_duplicates().array" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "\n", "['AC', 'AL', 'AM', 'AP', 'BA', 'CE', 'DF', 'ES', 'GO', 'MA', 'MG', 'MS', 'MT',\n", " 'PA', 'PB', 'PE', 'PI', 'PR', 'RJ', 'RN', 'RO', 'RR', 'RS', 'SC', 'SE', 'SP',\n", " 'TO']\n", "Length: 27, dtype: object" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ordena alfabeticamente\n", "covid_BR.estado.drop_duplicates().dropna().sort_values().array" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Agrupando dados por valores em colunas e agregando os resultados\n", "\n", "Vamos determinar uma coluna para agrupar. Consideraremos o *DataFrame* `covid_BR`e selecionaremos os estados *PB*, *PE*, *RJ* e *SP* para realizar análises agrupando os resultados por estados." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Unnamed: 0regiaoestadomunicipiocodufcodmuncodRegiaoSaudenomeRegiaoSaudedatasemanaEpipopulacaoTCU2019casosAcumuladocasosNovosobitosAcumuladoobitosNovosRecuperadosnovosemAcompanhamentoNovosinterior/metropolitana
17401740NordestePBNaN25NaNNaNNaN2020-02-25940181270000NaNNaNNaN
17411741NordestePBNaN25NaNNaNNaN2020-02-26940181270000NaNNaNNaN
17421742NordestePBNaN25NaNNaNNaN2020-02-27940181270000NaNNaNNaN
17431743NordestePBNaN25NaNNaNNaN2020-02-28940181270000NaNNaNNaN
17441744NordestePBNaN25NaNNaNNaN2020-02-29940181270000NaNNaNNaN
.........................................................
448655448655SudesteSPEstiva Gerbi35355730.035141.0BAIXA MOGIANA2020-07-14291130462631NaNNaN0.0
448656448656SudesteSPEstiva Gerbi35355730.035141.0BAIXA MOGIANA2020-07-15291130465330NaNNaN0.0
448657448657SudesteSPEstiva Gerbi35355730.035141.0BAIXA MOGIANA2020-07-16291130470530NaNNaN0.0
448658448658SudesteSPEstiva Gerbi35355730.035141.0BAIXA MOGIANA2020-07-17291130475541NaNNaN0.0
448659448659SudesteSPEstiva Gerbi35355730.035141.0BAIXA MOGIANA2020-07-18291130475040NaNNaN0.0
\n", "

130768 rows × 18 columns

\n", "
" ], "text/plain": [ " Unnamed: 0 regiao estado municipio coduf codmun \\\n", "1740 1740 Nordeste PB NaN 25 NaN \n", "1741 1741 Nordeste PB NaN 25 NaN \n", "1742 1742 Nordeste PB NaN 25 NaN \n", "1743 1743 Nordeste PB NaN 25 NaN \n", "1744 1744 Nordeste PB NaN 25 NaN \n", "... ... ... ... ... ... ... \n", "448655 448655 Sudeste SP Estiva Gerbi 35 355730.0 \n", "448656 448656 Sudeste SP Estiva Gerbi 35 355730.0 \n", "448657 448657 Sudeste SP Estiva Gerbi 35 355730.0 \n", "448658 448658 Sudeste SP Estiva Gerbi 35 355730.0 \n", "448659 448659 Sudeste SP Estiva Gerbi 35 355730.0 \n", "\n", " codRegiaoSaude nomeRegiaoSaude data semanaEpi \\\n", "1740 NaN NaN 2020-02-25 9 \n", "1741 NaN NaN 2020-02-26 9 \n", "1742 NaN NaN 2020-02-27 9 \n", "1743 NaN NaN 2020-02-28 9 \n", "1744 NaN NaN 2020-02-29 9 \n", "... ... ... ... ... \n", "448655 35141.0 BAIXA MOGIANA 2020-07-14 29 \n", "448656 35141.0 BAIXA MOGIANA 2020-07-15 29 \n", "448657 35141.0 BAIXA MOGIANA 2020-07-16 29 \n", "448658 35141.0 BAIXA MOGIANA 2020-07-17 29 \n", "448659 35141.0 BAIXA MOGIANA 2020-07-18 29 \n", "\n", " populacaoTCU2019 casosAcumulado casosNovos obitosAcumulado \\\n", "1740 4018127 0 0 0 \n", "1741 4018127 0 0 0 \n", "1742 4018127 0 0 0 \n", "1743 4018127 0 0 0 \n", "1744 4018127 0 0 0 \n", "... ... ... ... ... \n", "448655 11304 62 6 3 \n", "448656 11304 65 3 3 \n", "448657 11304 70 5 3 \n", "448658 11304 75 5 4 \n", "448659 11304 75 0 4 \n", "\n", " obitosNovos Recuperadosnovos emAcompanhamentoNovos \\\n", "1740 0 NaN NaN \n", "1741 0 NaN NaN \n", "1742 0 NaN NaN \n", "1743 0 NaN NaN \n", "1744 0 NaN NaN \n", "... ... ... ... \n", "448655 1 NaN NaN \n", "448656 0 NaN NaN \n", "448657 0 NaN NaN \n", "448658 1 NaN NaN \n", "448659 0 NaN NaN \n", "\n", " interior/metropolitana \n", "1740 NaN \n", "1741 NaN \n", "1742 NaN \n", "1743 NaN \n", "1744 NaN \n", "... ... \n", "448655 0.0 \n", "448656 0.0 \n", "448657 0.0 \n", "448658 0.0 \n", "448659 0.0 \n", "\n", "[130768 rows x 18 columns]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_BR.query('estado in [\"PB\", \"PE\", \"RJ\", \"SP\"]')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Inspecionando o conjunto de dados, observamos que os dados para estado são apresentados com o valor `NaN` para `codmun` e quando `codmun` possui um valor diferente de `NaN`, o resultado é apenas para o município do código em questão.\n", "\n", "Como estamos interessados nos valores por estado, vamos selecionar apenas os dados com `codmun` contendo `NaN`." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "covid_estados = covid_BR.query('estado in [\"PB\", \"PE\", \"RJ\", \"SP\"]')\n", "covid_apenas_estados = covid_estados.loc[covid_estados['codmun'].isna()]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora selecionar apenas as colunas de interesse. Para tanto, vejamos os nomes das colunas:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['Unnamed: 0', 'regiao', 'estado', 'municipio', 'coduf', 'codmun',\n", " 'codRegiaoSaude', 'nomeRegiaoSaude', 'data', 'semanaEpi',\n", " 'populacaoTCU2019', 'casosAcumulado', 'casosNovos', 'obitosAcumulado',\n", " 'obitosNovos', 'Recuperadosnovos', 'emAcompanhamentoNovos',\n", " 'interior/metropolitana'],\n", " dtype='object')" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_apenas_estados.columns" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "covid_apenas_estados = covid_apenas_estados[['estado', 'data', 'casosNovos', 'obitosNovos']]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "A data parece ser o *index* natural, já que o *index* atual não representa nada. Observe que teremos *index* repetidos, pois teremos as mesmas datas em estados diferentes." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
estadodatacasosNovosobitosNovos
1740PB2020-02-2500
1741PB2020-02-2600
1742PB2020-02-2700
1743PB2020-02-2800
1744PB2020-02-2900
...............
3040SP2020-07-1412000417
3041SP2020-07-156569316
3042SP2020-07-168872398
3043SP2020-07-175367339
3044SP2020-07-184612270
\n", "

580 rows × 4 columns

\n", "
" ], "text/plain": [ " estado data casosNovos obitosNovos\n", "1740 PB 2020-02-25 0 0\n", "1741 PB 2020-02-26 0 0\n", "1742 PB 2020-02-27 0 0\n", "1743 PB 2020-02-28 0 0\n", "1744 PB 2020-02-29 0 0\n", "... ... ... ... ...\n", "3040 SP 2020-07-14 12000 417\n", "3041 SP 2020-07-15 6569 316\n", "3042 SP 2020-07-16 8872 398\n", "3043 SP 2020-07-17 5367 339\n", "3044 SP 2020-07-18 4612 270\n", "\n", "[580 rows x 4 columns]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_apenas_estados" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "covid_apenas_estados = covid_apenas_estados.set_index('data')" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
estadocasosNovosobitosNovos
data
2020-02-25PB00
2020-02-26PB00
2020-02-27PB00
2020-02-28PB00
2020-02-29PB00
............
2020-07-14SP12000417
2020-07-15SP6569316
2020-07-16SP8872398
2020-07-17SP5367339
2020-07-18SP4612270
\n", "

580 rows × 3 columns

\n", "
" ], "text/plain": [ " estado casosNovos obitosNovos\n", "data \n", "2020-02-25 PB 0 0\n", "2020-02-26 PB 0 0\n", "2020-02-27 PB 0 0\n", "2020-02-28 PB 0 0\n", "2020-02-29 PB 0 0\n", "... ... ... ...\n", "2020-07-14 SP 12000 417\n", "2020-07-15 SP 6569 316\n", "2020-07-16 SP 8872 398\n", "2020-07-17 SP 5367 339\n", "2020-07-18 SP 4612 270\n", "\n", "[580 rows x 3 columns]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_apenas_estados" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Agrupando com o método *groupby*\n", "\n", "Podemos escolher uma (ou mais colunas, incluindo o índice) para agrupar os dados. Ao agruparmos os dados, receberemos um objeto do tipo `DataFrameGroupBy`. Para vermos os resultados, devemos agregar os valores:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "covid_estados_agrupado = covid_apenas_estados.groupby('estado')" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Casos TotaisObitos Totais
estado
PB669711477
PE785095928
RJ13523011919
SP41202719647
\n", "
" ], "text/plain": [ " Casos Totais Obitos Totais\n", "estado \n", "PB 66971 1477\n", "PE 78509 5928\n", "RJ 135230 11919\n", "SP 412027 19647" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_estados_agrupado.sum().rename({'casosNovos':'Casos Totais', 'obitosNovos':'Obitos Totais'},axis=1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Podemos agrupar por mais de uma coluna. Vamos fazer dois grupos. *grupo_1* formado por PB e PE e *grupo_2* formado por RJ e SP. Em seguida, vamos agrupar por grupo e por data:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "covid_estados_grupos = covid_apenas_estados.copy()\n", "col_grupos = covid_estados_grupos.estado.map(lambda estado: 'grupo_1' if estado in ['PB','PE']\n", " else 'grupo_2')\n", "covid_estados_grupos['grupo'] = col_grupos" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
estadocasosNovosobitosNovosgrupo
data
2020-02-25PB00grupo_1
2020-02-26PB00grupo_1
2020-02-27PB00grupo_1
2020-02-28PB00grupo_1
2020-02-29PB00grupo_1
...............
2020-07-14SP12000417grupo_2
2020-07-15SP6569316grupo_2
2020-07-16SP8872398grupo_2
2020-07-17SP5367339grupo_2
2020-07-18SP4612270grupo_2
\n", "

580 rows × 4 columns

\n", "
" ], "text/plain": [ " estado casosNovos obitosNovos grupo\n", "data \n", "2020-02-25 PB 0 0 grupo_1\n", "2020-02-26 PB 0 0 grupo_1\n", "2020-02-27 PB 0 0 grupo_1\n", "2020-02-28 PB 0 0 grupo_1\n", "2020-02-29 PB 0 0 grupo_1\n", "... ... ... ... ...\n", "2020-07-14 SP 12000 417 grupo_2\n", "2020-07-15 SP 6569 316 grupo_2\n", "2020-07-16 SP 8872 398 grupo_2\n", "2020-07-17 SP 5367 339 grupo_2\n", "2020-07-18 SP 4612 270 grupo_2\n", "\n", "[580 rows x 4 columns]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_estados_grupos" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Agora vamos agrupar e agregar:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "covid_grupo_agrupado = covid_estados_grupos.groupby(['grupo','data'])" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosNovosobitosNovos
grupodata
grupo_12020-02-2500
2020-02-2600
2020-02-2700
2020-02-2800
2020-02-2900
............
grupo_22020-07-1412778567
2020-07-158196449
2020-07-168996490
2020-07-176024409
2020-07-184612270
\n", "

290 rows × 2 columns

\n", "
" ], "text/plain": [ " casosNovos obitosNovos\n", "grupo data \n", "grupo_1 2020-02-25 0 0\n", " 2020-02-26 0 0\n", " 2020-02-27 0 0\n", " 2020-02-28 0 0\n", " 2020-02-29 0 0\n", "... ... ...\n", "grupo_2 2020-07-14 12778 567\n", " 2020-07-15 8196 449\n", " 2020-07-16 8996 490\n", " 2020-07-17 6024 409\n", " 2020-07-18 4612 270\n", "\n", "[290 rows x 2 columns]" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_grupo_agrupado.sum()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Mesclando *DataFrames* \n", "\n", "Vamos agora ver algumas formas de juntar dois ou mais *DataFrames* com *index* ou colunas em comum para formar um novo *DataFrame*.\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#### Mesclando *DataFrames* através de concatenações\n", "\n", "Concatenar nada mais é do que \"colar\" dois ou mais *DataFrames*. Podemos concatenar por linhas ou por colunas.\n", "\n", "A função que realiza a concatenação é `concat`. Os dois argumentos mais utilizados são a lista de *DataFrames* a serem concatenados e `axis`, onde `axis = 0` indica concatenação por linha (um *DataFrame* \"embaixo\" do outro) e `axis=1` indica concatenação por coluna (um *DataFrame* ao lado do outro)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Relembre do *DataFrame* `df_dict_series`:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "df_dict_series = pd.read_csv('../database/df_dict_series.csv')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos criar um novo, com novas pessoas:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "serie_Idade_nova = pd.Series({'Augusto':13, 'André': 17, 'Alexandre': 45}, name=\"Idade\")\n", "serie_Peso_novo = pd.Series({'Augusto':95, 'André': 65, 'Alexandre': 83}, name=\"Peso\")\n", "serie_Altura_nova = pd.Series({'Augusto':192, 'André': 175, 'Alexandre': 177}, name=\"Altura\")\n", "serie_sobrenome = pd.Series({'Augusto':'Castro', 'André':'Castro', 'Alexandre':'Castro'}, name='Sobrenome')\n", "dicionario_novo = {'Sobrenome':serie_sobrenome, 'Peso': serie_Peso_novo, \n", " 'Idade': serie_Idade_nova, 'Altura': serie_Altura_nova}\n", "df_novo = pd.DataFrame(dicionario_novo)\n", "df_novo = df_novo.assign(IMC=round(df_novo.eval('Peso/(Altura/100)**2'),2))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
SobrenomePesoIdadeAlturaIMC
AugustoCastro951319225.77
AndréCastro651717521.22
AlexandreCastro834517726.49
\n", "
" ], "text/plain": [ " Sobrenome Peso Idade Altura IMC\n", "Augusto Castro 95 13 192 25.77\n", "André Castro 65 17 175 21.22\n", "Alexandre Castro 83 45 177 26.49" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_novo" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Agora vamos concatená-los:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Unnamed: 0IdadePesoAlturaIMCSobrenome
0Ana206516224.77Silva
1João198017825.25PraDo
2Maria216216223.62Sales
3Pedro226716524.61MachadO
4Túlio207317124.96Coutinho
AugustoNaN139519225.77Castro
AndréNaN176517521.22Castro
AlexandreNaN458317726.49Castro
\n", "
" ], "text/plain": [ " Unnamed: 0 Idade Peso Altura IMC Sobrenome\n", "0 Ana 20 65 162 24.77 Silva\n", "1 João 19 80 178 25.25 PraDo\n", "2 Maria 21 62 162 23.62 Sales\n", "3 Pedro 22 67 165 24.61 MachadO\n", "4 Túlio 20 73 171 24.96 Coutinho\n", "Augusto NaN 13 95 192 25.77 Castro\n", "André NaN 17 65 175 21.22 Castro\n", "Alexandre NaN 45 83 177 26.49 Castro" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([df_dict_series,df_novo]) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Concatenando por coluna\n", "\n", "Para exemplificar vamos considerar os dados de COVID da Paraíba, selecionando casos novos e óbitos novos, e vamos obter dos dados do Brasil apenas os casos e óbitos diários do país, e vamos concatená-los por coluna." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "covid_PB_casos_obitos = dados_covid_PB[['casosNovos','obitosNovos']]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos tratar os dados do Brasil:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "covid_BR_casos_obitos = covid_BR.query('regiao==\"Brasil\"')\n", "covid_BR_casos_obitos = covid_BR_casos_obitos.set_index('data')\n", "covid_BR_casos_obitos = covid_BR_casos_obitos[['casosNovos','obitosNovos']].rename({\n", " 'casosNovos':'casosBR', 'obitosNovos':'obitosBR'\n", "}, axis=1)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosNovosobitosNovos
data
2021-09-261342.0
2021-09-251652.0
2021-09-242253.0
2021-09-232033.0
2021-09-222976.0
.........
2020-03-2000.0
2020-03-1900.0
2020-03-1800.0
2020-03-1700.0
2020-03-1600.0
\n", "

559 rows × 2 columns

\n", "
" ], "text/plain": [ " casosNovos obitosNovos\n", "data \n", "2021-09-26 134 2.0\n", "2021-09-25 165 2.0\n", "2021-09-24 225 3.0\n", "2021-09-23 203 3.0\n", "2021-09-22 297 6.0\n", "... ... ...\n", "2020-03-20 0 0.0\n", "2020-03-19 0 0.0\n", "2020-03-18 0 0.0\n", "2020-03-17 0 0.0\n", "2020-03-16 0 0.0\n", "\n", "[559 rows x 2 columns]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_PB_casos_obitos" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosBRobitosBR
data
2020-02-2500
2020-02-2610
2020-02-2700
2020-02-2800
2020-02-2910
.........
2020-07-14418571300
2020-07-15399241233
2020-07-16454031322
2020-07-17341771163
2020-07-1828532921
\n", "

145 rows × 2 columns

\n", "
" ], "text/plain": [ " casosBR obitosBR\n", "data \n", "2020-02-25 0 0\n", "2020-02-26 1 0\n", "2020-02-27 0 0\n", "2020-02-28 0 0\n", "2020-02-29 1 0\n", "... ... ...\n", "2020-07-14 41857 1300\n", "2020-07-15 39924 1233\n", "2020-07-16 45403 1322\n", "2020-07-17 34177 1163\n", "2020-07-18 28532 921\n", "\n", "[145 rows x 2 columns]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "covid_BR_casos_obitos" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora concatená-los por coluna:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosNovosobitosNovoscasosBRobitosBR
data
2021-09-26134.02.0NaNNaN
2021-09-25165.02.0NaNNaN
2021-09-24225.03.0NaNNaN
2021-09-23203.03.0NaNNaN
2021-09-22297.06.0NaNNaN
...............
2020-03-11NaNNaN18.00.0
2020-03-12NaNNaN25.00.0
2020-03-13NaNNaN21.00.0
2020-03-14NaNNaN23.00.0
2020-03-15NaNNaN79.00.0
\n", "

579 rows × 4 columns

\n", "
" ], "text/plain": [ " casosNovos obitosNovos casosBR obitosBR\n", "data \n", "2021-09-26 134.0 2.0 NaN NaN\n", "2021-09-25 165.0 2.0 NaN NaN\n", "2021-09-24 225.0 3.0 NaN NaN\n", "2021-09-23 203.0 3.0 NaN NaN\n", "2021-09-22 297.0 6.0 NaN NaN\n", "... ... ... ... ...\n", "2020-03-11 NaN NaN 18.0 0.0\n", "2020-03-12 NaN NaN 25.0 0.0\n", "2020-03-13 NaN NaN 21.0 0.0\n", "2020-03-14 NaN NaN 23.0 0.0\n", "2020-03-15 NaN NaN 79.0 0.0\n", "\n", "[579 rows x 4 columns]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([covid_PB_casos_obitos, covid_BR_casos_obitos], axis=1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Para um polimento final, vamos substituir os valores `NaN` que ocorreram antes do dia 13 de julho por 0. Para tanto, a forma ideal é utilizando o método `map`:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosNovosobitosNovoscasosBRobitosBR
data
2021-09-261342NaNNaN
2021-09-251652NaNNaN
2021-09-242253NaNNaN
2021-09-232033NaNNaN
2021-09-222976NaNNaN
...............
2020-03-110018.00.0
2020-03-120025.00.0
2020-03-130021.00.0
2020-03-140023.00.0
2020-03-150079.00.0
\n", "

579 rows × 4 columns

\n", "
" ], "text/plain": [ " casosNovos obitosNovos casosBR obitosBR\n", "data \n", "2021-09-26 134 2 NaN NaN\n", "2021-09-25 165 2 NaN NaN\n", "2021-09-24 225 3 NaN NaN\n", "2021-09-23 203 3 NaN NaN\n", "2021-09-22 297 6 NaN NaN\n", "... ... ... ... ...\n", "2020-03-11 0 0 18.0 0.0\n", "2020-03-12 0 0 25.0 0.0\n", "2020-03-13 0 0 21.0 0.0\n", "2020-03-14 0 0 23.0 0.0\n", "2020-03-15 0 0 79.0 0.0\n", "\n", "[579 rows x 4 columns]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_PB_BR = pd.concat([covid_PB_casos_obitos, covid_BR_casos_obitos], axis=1)\n", "dados_PB_BR['casosNovos'] = dados_PB_BR.casosNovos.map(lambda caso: 0 if np.isnan(caso) else caso).astype('int')\n", "dados_PB_BR['obitosNovos'] = dados_PB_BR.obitosNovos.map(lambda obito: 0 if np.isnan(obito) else obito).astype('int')\n", "dados_PB_BR" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Mesclando *DataFrames* através de *joins*\n", "\n", "Para realizar *joins* iremos utilizar a função `merge` do *pandas*. *joins* tomam duas tabelas, uma tabela à esquerda e uma à direita e retornam uma terceira tabela contendo a união das colunas das duas tabelas." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Existem 4 tipos de *joins*:\n", "\n", "* *left join*: Apenas irão aparecer os *index* (da linha) que existem na tabela à esquerda;\n", "* *right join*: Apenas irão aparecer os *index* (da linha) que existem na tabela à direita;\n", "* *inner join*: Apenas irão aparecer os *index* que existem nas duas tabelas;\n", "* *full join* ou *outer join*: irão aparecer todos os *index* das duas tabelas." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Para exemplificar vamos considerar dois *DataFrames* (aqui teremos menos linhas, com nomes e dados fictícios). O primeiro *DataFrame* consistirá de nomes de alunos, CPF e matrícula da UFPB (*nome_cpf_mat*). O segundo *DataFrame* consistirá de nome, CPF e e-mail (*nome_cpf_email*). Nosso objetivo é criar um novo *DataFrame* contendo Nome, CPF, matrícula e e-mail." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Temos ainda as seguintes situações:\n", "\n", "- No *DataFrame* *nome_cpf_mat* existem alunos que não estão presentes no *nome_cpf_email*, pois não enviaram esta informação.\n", "\n", "- No *DataFrame* *nome_cpf_email* existem alunos que não estão presentes no *nome_cpf_mat* pois estes não são alunos da UFPB." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "nome_cpf_mat = pd.read_csv('../database/nome_cpf_mat.csv')\n", "nome_cpf_email = pd.read_csv('../database/nome_cpf_email.csv')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora examinar os *DataFrames*. Como são bem simples, basta realizar *prints* deles." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeCPFMatricula
0João Paulo326.475.190-998848484
1Ana Silva073.101.240-228451212
2Antonio Carlos830.060.930-035151213
3Debora Santos472.006.460-4051848484
4Rodrigo Gomes566.712.550-161415816
5Edson Jardim308.226.400-079592303
\n", "
" ], "text/plain": [ " Nome CPF Matricula\n", "0 João Paulo 326.475.190-99 8848484\n", "1 Ana Silva 073.101.240-22 8451212\n", "2 Antonio Carlos 830.060.930-03 5151213\n", "3 Debora Santos 472.006.460-40 51848484\n", "4 Rodrigo Gomes 566.712.550-16 1415816\n", "5 Edson Jardim 308.226.400-07 9592303" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nome_cpf_mat" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeCPFe-mail
0João Paulo326.475.190-99joao@inventado.com.br
1Ana Silva073.101.240-22ana@inventado.com.br
2Antonio Carlos830.060.930-03antonio@inventado.com.br
3Saulo Santos370.981.810-99saulo@inventado.com.br
4Paulo Cardoso250.078.710-95paulo@inventado.com.br
5Edson Jardim308.226.400-07edson@inventado.com.br
6Ana Silva344.246.630-00anasilva@inventado.com.br
\n", "
" ], "text/plain": [ " Nome CPF e-mail\n", "0 João Paulo 326.475.190-99 joao@inventado.com.br\n", "1 Ana Silva 073.101.240-22 ana@inventado.com.br\n", "2 Antonio Carlos 830.060.930-03 antonio@inventado.com.br\n", "3 Saulo Santos 370.981.810-99 saulo@inventado.com.br\n", "4 Paulo Cardoso 250.078.710-95 paulo@inventado.com.br\n", "5 Edson Jardim 308.226.400-07 edson@inventado.com.br\n", "6 Ana Silva 344.246.630-00 anasilva@inventado.com.br" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nome_cpf_email" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Tipicamente é bom possuir *index* únicos. Neste sentido, vamos definir o CPF como *index*:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "nome_cpf_mat = nome_cpf_mat.set_index('CPF')\n", "nome_cpf_email = nome_cpf_email.set_index('CPF')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora realizar um **left** join com o *DataFrame* **nome_cpf_mat** ficando à esquerda (neste caso, apenas alunos com matrícula irão aparecer):" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeMatriculae-mail
CPF
326.475.190-99João Paulo8848484joao@inventado.com.br
073.101.240-22Ana Silva8451212ana@inventado.com.br
830.060.930-03Antonio Carlos5151213antonio@inventado.com.br
472.006.460-40Debora Santos51848484NaN
566.712.550-16Rodrigo Gomes1415816NaN
308.226.400-07Edson Jardim9592303edson@inventado.com.br
\n", "
" ], "text/plain": [ " Nome Matricula e-mail\n", "CPF \n", "326.475.190-99 João Paulo 8848484 joao@inventado.com.br\n", "073.101.240-22 Ana Silva 8451212 ana@inventado.com.br\n", "830.060.930-03 Antonio Carlos 5151213 antonio@inventado.com.br\n", "472.006.460-40 Debora Santos 51848484 NaN\n", "566.712.550-16 Rodrigo Gomes 1415816 NaN\n", "308.226.400-07 Edson Jardim 9592303 edson@inventado.com.br" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(nome_cpf_mat, nome_cpf_email, how = 'left', on = ['Nome','CPF'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "- Na opção *how* dizemos qual o tipo de *join* que queremos realizar. \n", "\n", "- Na opção *on* dizemos quais as colunas que existem em comum nos *DataFrames*.\n", "\n", "Veja o que aconteceria se informássemos apenas que o *CPF* está presente nos dois *DataFrames*:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Nome_xMatriculaNome_ye-mail
CPF
326.475.190-99João Paulo8848484João Paulojoao@inventado.com.br
073.101.240-22Ana Silva8451212Ana Silvaana@inventado.com.br
830.060.930-03Antonio Carlos5151213Antonio Carlosantonio@inventado.com.br
472.006.460-40Debora Santos51848484NaNNaN
566.712.550-16Rodrigo Gomes1415816NaNNaN
308.226.400-07Edson Jardim9592303Edson Jardimedson@inventado.com.br
\n", "
" ], "text/plain": [ " Nome_x Matricula Nome_y \\\n", "CPF \n", "326.475.190-99 João Paulo 8848484 João Paulo \n", "073.101.240-22 Ana Silva 8451212 Ana Silva \n", "830.060.930-03 Antonio Carlos 5151213 Antonio Carlos \n", "472.006.460-40 Debora Santos 51848484 NaN \n", "566.712.550-16 Rodrigo Gomes 1415816 NaN \n", "308.226.400-07 Edson Jardim 9592303 Edson Jardim \n", "\n", " e-mail \n", "CPF \n", "326.475.190-99 joao@inventado.com.br \n", "073.101.240-22 ana@inventado.com.br \n", "830.060.930-03 antonio@inventado.com.br \n", "472.006.460-40 NaN \n", "566.712.550-16 NaN \n", "308.226.400-07 edson@inventado.com.br " ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(nome_cpf_mat, nome_cpf_email, how = 'left', on = 'CPF')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Observe que os nomes dos alunos que estão na segunda tabela ficam indeterminados na coluna *Nome_y*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora realizar um **right** join com o *DataFrame* **nome_cpf_mat** ficando à esquerda (neste caso, apenas alunos **com e-mail** irão aparecer):" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeMatriculae-mail
CPF
326.475.190-99João Paulo8848484.0joao@inventado.com.br
073.101.240-22Ana Silva8451212.0ana@inventado.com.br
830.060.930-03Antonio Carlos5151213.0antonio@inventado.com.br
370.981.810-99Saulo SantosNaNsaulo@inventado.com.br
250.078.710-95Paulo CardosoNaNpaulo@inventado.com.br
308.226.400-07Edson Jardim9592303.0edson@inventado.com.br
344.246.630-00Ana SilvaNaNanasilva@inventado.com.br
\n", "
" ], "text/plain": [ " Nome Matricula e-mail\n", "CPF \n", "326.475.190-99 João Paulo 8848484.0 joao@inventado.com.br\n", "073.101.240-22 Ana Silva 8451212.0 ana@inventado.com.br\n", "830.060.930-03 Antonio Carlos 5151213.0 antonio@inventado.com.br\n", "370.981.810-99 Saulo Santos NaN saulo@inventado.com.br\n", "250.078.710-95 Paulo Cardoso NaN paulo@inventado.com.br\n", "308.226.400-07 Edson Jardim 9592303.0 edson@inventado.com.br\n", "344.246.630-00 Ana Silva NaN anasilva@inventado.com.br" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(nome_cpf_mat, nome_cpf_email, how = 'right', on = ['Nome','CPF'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos agora realizar um **inner** join com o *DataFrame* **nome_cpf_mat** ficando à esquerda (neste caso, apenas alunos **com matrícula e com e-mail** irão aparecer):" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeMatriculae-mail
CPF
326.475.190-99João Paulo8848484joao@inventado.com.br
073.101.240-22Ana Silva8451212ana@inventado.com.br
830.060.930-03Antonio Carlos5151213antonio@inventado.com.br
308.226.400-07Edson Jardim9592303edson@inventado.com.br
\n", "
" ], "text/plain": [ " Nome Matricula e-mail\n", "CPF \n", "326.475.190-99 João Paulo 8848484 joao@inventado.com.br\n", "073.101.240-22 Ana Silva 8451212 ana@inventado.com.br\n", "830.060.930-03 Antonio Carlos 5151213 antonio@inventado.com.br\n", "308.226.400-07 Edson Jardim 9592303 edson@inventado.com.br" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(nome_cpf_mat, nome_cpf_email, how = 'inner', on = ['Nome','CPF'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Por fim, vamos agora realizar um **outer** ou **full** join com o *DataFrame* **nome_cpf_mat** ficando à esquerda (neste caso, **todos** os alunos irão aparecer):" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NomeMatriculae-mail
CPF
326.475.190-99João Paulo8848484.0joao@inventado.com.br
073.101.240-22Ana Silva8451212.0ana@inventado.com.br
830.060.930-03Antonio Carlos5151213.0antonio@inventado.com.br
472.006.460-40Debora Santos51848484.0NaN
566.712.550-16Rodrigo Gomes1415816.0NaN
308.226.400-07Edson Jardim9592303.0edson@inventado.com.br
370.981.810-99Saulo SantosNaNsaulo@inventado.com.br
250.078.710-95Paulo CardosoNaNpaulo@inventado.com.br
344.246.630-00Ana SilvaNaNanasilva@inventado.com.br
\n", "
" ], "text/plain": [ " Nome Matricula e-mail\n", "CPF \n", "326.475.190-99 João Paulo 8848484.0 joao@inventado.com.br\n", "073.101.240-22 Ana Silva 8451212.0 ana@inventado.com.br\n", "830.060.930-03 Antonio Carlos 5151213.0 antonio@inventado.com.br\n", "472.006.460-40 Debora Santos 51848484.0 NaN\n", "566.712.550-16 Rodrigo Gomes 1415816.0 NaN\n", "308.226.400-07 Edson Jardim 9592303.0 edson@inventado.com.br\n", "370.981.810-99 Saulo Santos NaN saulo@inventado.com.br\n", "250.078.710-95 Paulo Cardoso NaN paulo@inventado.com.br\n", "344.246.630-00 Ana Silva NaN anasilva@inventado.com.br" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(nome_cpf_mat, nome_cpf_email, how = 'outer', on = ['Nome','CPF'])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Os métodos *apply*, *map* e *applymap*\n", "\n", "A ideia é relativamente simples. Os três métodos são vetorizados e aplicam uma função ou uma substituição via dicionário de tal forma que:\n", "\n", "* *apply* é realizado via linha ou coluna em um *DataFrame*;\n", "* *map* é aplicado a cada elemento de uma *Series*;\n", "* *applymap* é aplicado a cada elemento de um *DataFrame*.\n", "\n", "Já vimos diversos exemplos de uso de `map`. Vejamos exemplos de `applymap` e `apply`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "* Neste exemplo vamos retomar a concatenação entre os dados da Paraíba e do Brasil, porém iremos substituir *todos* os valores de `NaN` por zero, usando o métodp `applymap`." ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
casosNovosobitosNovoscasosBRobitosBR
data
2021-09-26134.02.00.00.0
2021-09-25165.02.00.00.0
2021-09-24225.03.00.00.0
2021-09-23203.03.00.00.0
2021-09-22297.06.00.00.0
...............
2020-03-110.00.018.00.0
2020-03-120.00.025.00.0
2020-03-130.00.021.00.0
2020-03-140.00.023.00.0
2020-03-150.00.079.00.0
\n", "

579 rows × 4 columns

\n", "
" ], "text/plain": [ " casosNovos obitosNovos casosBR obitosBR\n", "data \n", "2021-09-26 134.0 2.0 0.0 0.0\n", "2021-09-25 165.0 2.0 0.0 0.0\n", "2021-09-24 225.0 3.0 0.0 0.0\n", "2021-09-23 203.0 3.0 0.0 0.0\n", "2021-09-22 297.0 6.0 0.0 0.0\n", "... ... ... ... ...\n", "2020-03-11 0.0 0.0 18.0 0.0\n", "2020-03-12 0.0 0.0 25.0 0.0\n", "2020-03-13 0.0 0.0 21.0 0.0\n", "2020-03-14 0.0 0.0 23.0 0.0\n", "2020-03-15 0.0 0.0 79.0 0.0\n", "\n", "[579 rows x 4 columns]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_PB_BR = pd.concat([covid_PB_casos_obitos, covid_BR_casos_obitos], axis=1)\n", "dados_PB_BR.applymap(lambda valor: 0 if np.isnan(valor) else valor)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Vamos utilizar `apply` para realizar a soma de casos e óbitos através de mais de uma forma" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "casosNovos 440037\n", "obitosNovos 9294\n", "casosBR 2074860\n", "obitosBR 78772\n", "dtype: int64" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_PB_BR.apply(lambda x: np.sum(x)).astype('int')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Se quisermos realizar a operação por linhas, basta utilizar o argumento `axis=1`:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "data\n", "2021-09-26 False\n", "2021-09-25 False\n", "2021-09-24 False\n", "2021-09-23 False\n", "2021-09-22 False\n", " ... \n", "2020-03-11 False\n", "2020-03-12 False\n", "2020-03-13 False\n", "2020-03-14 False\n", "2020-03-15 False\n", "Length: 579, dtype: bool" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dados_PB_BR.apply(lambda x: (x>0).all(), axis=1)" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" }, "latex_metadata": { "affiliation": "Departamento de Computação Científica / UFPB", "author": "Gustavo Oliveira e Andréa Rocha", "date": "Julho de 2020", "title": "Aula 6B - Manipulação de Dados" }, "rise": { "enable_chalkboard": true, "footer": "UFPB - CI - DCC", "header": "Gustavo Oliveira / Andrea Rocha", "theme": "sky" } }, "nbformat": 4, "nbformat_minor": 4 }