Controle da evolução corporal

Em processo de emagrecer registrando as medidas de "sucesso"

Sempre tive um barriguinha redonda, na minha guerra constante resolvi usar um pouco de ciência de dados para ajudar em mais uma batalha, me desafiando por 100 dias para alcançar 85Kg
O projeto completo está no Repositorio GitHub

Carregar os dados

Definindo o foco de 100 dias para alcançar os 85Kg desejados

focoDias = 100
focoPeso = 85

Usando o arquivo de dados em csv com o seguinte formato

Data,Peso,Imagem,AtividadeFisica,AlimentacaoTipo,AlimentacaoNivel,AlimentacaoCondicao
2018-09-23,96.7,1.jpg,'[{"Tipo":"Corrida", "Distancia":5.43, "Velocidade":9.92}]','["Laticínios", "Frutas"]',Moderada,
2018-09-24,96.1,,'[{"Tipo":"Corrida", "Distancia":5.40, "Velocidade":9.80}]','["Frutas", "Legumes", "Raízes"]',Moderada,
2018-09-25,94.7,,'[{"Tipo":"Musculação", "Foco":"Pernas"}]','["Frutas", "Legumes", "Raízes"]',Baixa,
2018-09-26,94.4,,,'["Frutas", "Raízes"]',Moderada,

Carregando os dados as bibliotecas de pandas, manipular os dados, e numpy, funções matemáticas.
Lendo e carregando o arquivo convertendo os textos em json, para acumular os históricos de atividades físicas e tipo de alimentação ambos objetos com listagens

import pandas as pd
import numpy as np

def LerJSON(data):
    import json
    if (data == ''):
        return json.loads('[]')
    else:
        return json.loads(data)

df_dados = pd.read_csv('./dados.csv', quotechar='\'', converters={'AtividadeFisica':LerJSON, 'AlimentacaoTipo':LerJSON}, header=0)

Cálculo do limite de peso

Extraindo os dados de contagem e valor máximo das medidas, posteriormente usando extrapolação linear para preencher os dados faltantes

count = df_dados['Peso'].count()
max = df_dados['Peso'].max()
df_dados['Peso'] = df_dados['Peso'].interpolate()

Com uma projeção linear de peso máximo para o objetivo

linha_limite = pd.Series(range(0, focoDias))
linha_limite = max - (linha_limite * ((max - focoPeso) / focoDias))
df_dados['Limite'] = linha_limite

Nível de atividades físicas

Para o resultado do fluxo ser negativo é necessário ter saída, aumentar esse fluxo com muita atividade física

def scoreAtividade(data):
    score = 0
    for atividade in data:
        score = score + {
            'Corrida': lambda: atividade['Distancia'] * atividade['Velocidade'],
            'Caminhada': lambda: atividade['Distancia'] * atividade['Velocidade'] * 0.5,
            'Funcional': lambda: 30,
            'Musculação': lambda: 15,
        }.get(atividade['Tipo'], lambda: 0)()
    return score
df_dados['ScoreAtividade'] = df_dados['AtividadeFisica'].apply(scoreAtividade)
df_dados['ScoreAtividade'] = 15 * df_dados['ScoreAtividade']

Usando elevação de 2, para impedir que as somas deve possuir um valor igual com os outros

def tipoAtividade(data):
    tipo = 0
    for atividade in data:
        tipo = tipo + {
            'Corrida': lambda: 1,
            'Musculação': lambda: 2,
            'Funcional': lambda: 4
        }.get(atividade['Tipo'], lambda: 0)()
    return tipo
df_dados['Tipo'] = df_dados['AtividadeFisica'].apply(tipoAtividade)

Nível de alimentação

Usando as regras de

def tipoAlimentacao(data):
    tipo = 0
    for alimentacao in data:
        tipo = tipo + {
            'Raízes': lambda: 1,
            'Legumes': lambda: 2,
            'Frutas': lambda: 4,
            'Laticínios': lambda: 8,
            'Farinários': lambda: 16,
            'Proteína Animal': lambda: 32,
            'Açúcar': lambda: 64
        }.get(alimentacao, lambda: 0)()
    return tipo
def nivelAlimentacao(data):
    return {
        'Baixa': lambda: 1,
        'Moderada': lambda: 2,
        'Alta': lambda: 4,
        'Exagerada': lambda: 8,
    }.get(data, lambda: 0)()
alimentacaoTipo = df_dados['AlimentacaoTipo'].apply(tipoAlimentacao)
alimentacaoVolume = df_dados['AlimentacaoNivel'].apply(nivelAlimentacao)
df_dados["ScoreAlimentacao"] = 0.025 * np.sqrt(alimentacaoTipo * alimentacaoVolume)

Número de dias

Adicionando a coluna de Número de dias para facilitar no processo

df_dados["NumeroDias"] = df_dados.index + 1

Geração do gráfico

E finalmente gerando a visualização

import matplotlib.pyplot as plt
plt.plot(df_dados["NumeroDias"], df_dados["Peso"])
plt.plot(df_dados["NumeroDias"], df_dados["Limite"])
plt.scatter(df_dados["NumeroDias"], df_dados["Peso"],
    s=df_dados["ScoreAtividade"], c=df_dados["Tipo"], alpha=0.5)
plt.errorbar(df_dados["NumeroDias"], df_dados["Peso"],
    yerr=df_dados['ScoreAlimentacao'], ecolor="grey", elinewidth=4, alpha=0.75, fmt='none')
plt.xlabel("Dias")
plt.ylabel("Medida")
plt.legend(['Evolução', 'Objetivo'])
plt.savefig('evolution.png', dpi=300)
plt.show()

plot of chunk controle_peso

Visualização da Tabela

tabela = df_dados[['Data', 'NumeroDias', 'Peso', 'Limite', 'ScoreAtividade', 'ScoreAlimentacao', 'AlimentacaoCondicao']]
tabela.to_csv('dadosOrganizados.csv')
tabela.head(15)

Compartilhe:

Algumas recomendações

{JWA}

Johny W. Alves | Web Developer