====== Silas Principe ====== {{:bie5782:01_curso_atual:alunos:trabalho_final:silasprincipe:dsc03909_2_.jpg?200|}} Doutorando em Oceanografia (Oceanografia Biológica), Instituto Oceanográfico, USP Minha pesquisa visa modelar a distribuição de espécies de ambientes costeiros rasos em alguns cenários climáticos futuros para entender como as mudanças climáticas poderão afetar essas espécies e as comunidades associadas. ---- ===== Exercícios ===== [[.:exec]] ---- ===== Trabalho final ===== ==== Proposta A: visualR ==== === Função para criar diagramas === \\ Diagramas e mapas conceituais são ferramentas úteis para a melhor compreensão de questões científicas. O raciocínio lógico é consideravelmente ampliado quando diagramas são utilizados [1]. Na área da saúde, por exemplo, o uso de diagramas diretos acíclicos (DAG, Direct Acyclic Graphs) é utilizado para verificar variáveis para as quais é necessário um ajuste na análise [2].\\ A proposta é criar uma função que permita ao usuário criar diagramas/mapas conceituais de maneira manual, alem de dar a opção de criar um DAG automaticamente. A ideia para essa proposta surgiu após um amigo, que cursa pós em nutrição, me procurar para entender alguns pontos de um artigo. Quando me deparei com o DAG vi as potencialidades de seu uso e resolvi tentar criar essa função. \\ \\ **Plano da função:** \\ \\ **Entrada:** visualR(text, color, line, words, arrows, rectangle, font) '' text '' = vetor com as palavras/números que devem ser inseridos no diagrama. Todos os valores serão convertidos para a classe "character". Opcional. (classe: character, numeric ou factor) \\ '' color '' = opcional, define a cor dos retângulos e setas do diagrama (uso com palavras como "red", "blue", ou RGB). (classe: character) \\ '' line '' = opcional, por padrão é do tipo 2. Define o tipo de seta que será usado ou se o usuário usará apenas linhas (será definido no help). (classe: numeric) \\ '' words '' = opcional caso ''text'' não seja definido. Delimita quantas palavras o usuário poderá inserir. Caso ''text'' esteja presente, é ignorado. Se ''text'' e ''words'' não for especificado, o usuário terá a opção de digitar até 200 palavras, com opção de parar quando desejar. (classe: numeric)\\ '' arrows '' = opcional caso ''text'' não seja definido. Delimita quantas setas ou linhas o usuário poderá inserir. Se ''text'' e ''words'' não for especificado, o usuário terá a opção de desenhar até 200 setas/linhas, com opção de parar quando desejar. (classe: numeric)\\ '' rectangle '' = por padrão é ''TRUE''. Caso o usuário não deseje retângulos ao redor do texto, pode optar por ''FALSE''.\\ '' font '' = permite ao usuário escolher o tipo de fonte que será usado (especificado no help da função ''par'', em ''family''). \\ \\ **Verificando os parâmetros** '' text '' é do tipo character? Se não, converte para character. Verifica o tamanho do vetor. O vetor tem comprimento maior do que dois? Se não, para a função e escreve "TEXT deve ser um vetor com comprimento maior do que dois".\\ '' words '' e ''text'' estão presentes juntos? Se sim, escreve "WORDS não é um argumento quando TEXT está presente. Ele será ignorado." e continua a função\\ Se ''text'' está ausente e ''words'' também, imprime a mensagem: "WORDS e TEXT não especificados. O usuário terá um limite de 200 palavras, podendo parar quando quiser."\\ '' arrows '' é um valor maior do que 0? Se não, para a função e escreve "ARROWS deve ser um valor maior do que 0". \\ \\ **Pseudo-código** - Cria um espaço gráfico com configurações padrões\\ - Se ''text'' está presente - Cria o objeto ''qt'' com o comprimento de ''text'' - Se ''text'' não está presente, mas ''words'' está - Insere o valor de ''words'' em um objeto ''qt'' - Se ''text'' e ''words'' não estão presentes - Cria objeto ''qt'' com valor 200 - Plota um gráfico de 0:50 nos dois eixos, sem nenhum tipo de informação (espaço em branco)\\ - Se ''text'' e ''words'' não estão presentes - Usando for de 1:qt - Imprime a mensagem "onde você quer o texto?" - Cria o vetor ''point'' com locator(1) (usuário clica onde quer o texto no gráfico) - Apresenta a mensagem "Escreva seu texto (max 10 caracteres) ou digite END para encerrar a digitação de textos." (dentro da função readline) - Cria o vetor ''text.r'' com o texto inserido pelo usuário usando a função readline - Se text.r for END, encerra a digitação de textos e vai para a inserção de linhas. Se não: - Verifica se o texto inserido está dentro do máximo permitido de caracteres (10, se não ocupa muito espaço) - Se não, mostra mensagem avisando que o texto é maior que o máximo permitido e pede para o usuário escrever de novo - Se novamente o texto estiver maior que 10 caracteres, para a função e exibe mensagem de erro - Se ''rectangle'' é TRUE - Cria os objetos ''text.w'' e ''text.h'' com o comprimento e a altura, respectivamente, de ''text.r'' - Cria um vetor x0 com o valor de x em ''point'' - ''sw'' - Cria um vetor x1 com o valor de x em ''point'' + ''sw'' - Cria um vetor y0 com o valor de y em ''point'' - ''sh'' - Cria um vetor y1 com o valor de y em ''point'' + ''sh'' - Cria um retangulo com x0, y0, x1, y1 e cor rgb pegando a posição i de cada coluna de colors. - Adiciona o texto da posição i de ''text'' na posição x e y de ''point'' - Usando for de 1:qt (ou arrows, se ''arrows'' estiver presente) - Imprime a mensagem "onde você quer a flecha?" - Cria o vetor ''point'' com locator(2) - Cria um objeto ''point'' com os valores de locator(2) (usuário deverá clicar no gráfico duas vezes, ponto inicial e final da linha) - Gera a linha com a posição x1, x2, y1, y2 de ''point'', parâmetro ''line'' e cor ''colors''. - Pergunta se o usuário quer inserir outra linha (usando readline). Se não, usa ''return'' para encerrar o diagrama. - Se ''text'' ou ''words'' estão presentes - Usando um for de 1:qt - Cria um objeto ''point'' com o valor de locator(1) (usuário deverá clicar no gráfico uma vez para cada palavra) - Se text não está presente - Cria o vetor ''text.r'' com o texto inserido pelo usuário usando a função readline - Verifica se o texto inserido está dentro do máximo permitido de caracteres (10, se não ocupa muito espaço) - Se não, mostra mensagem avisando que o texto é maior que o máximo permitido e pede para o usuário escrever de novo - Se novamente o texto estiver maior que 10 caracteres, para a função e exibe mensagem de erro - Se ''rectangle'' é TRUE - Se text está presente - Cria os objetos ''text.w'' e ''text.h'' com o comprimento e a altura, respectivamente, do texto na posição i de ''text'' - Se text não está presente - Cria os objetos ''text.w'' e ''text.h'' com o comprimento e a altura, respectivamente, de ''text.r'' - Cria um vetor x0 com o valor de x em ''point'' - ''sw'' - Cria um vetor x1 com o valor de x em ''point'' + ''sw'' - Cria um vetor y0 com o valor de y em ''point'' - ''sh'' - Cria um vetor y1 com o valor de y em ''point'' + ''sh'' - Cria um retangulo com x0, y0, x1, y1 e cor ''colors''. - Se text está presente - Adiciona o texto da posição i de ''text'' na posição x e y de ''point'' - Se text não está presente - Adiciona o texto de text.r na posição x e y de ''point'' - Usando um for de 1:qt (ou de 1:arrow, caso ''arrow'' esteja presente). - Cria um objeto ''point'' com os valores de locator(2) (usuário deverá clicar no gráfico duas vezes, ponto inicial e final da linha) - Gera a linha com a posição x1, x2, y1, y2 de ''point'', parâmetro ''line'' e cor ''colors''. \\ \\ **Saída** - Retorna um objeto gráfico com o diagrama escolhido. --- //[[delbel.renan@gmail.com|Renan Del Bel]] 2019/06/13 12:53// Toda a parte relacionada a DAG é muito confusa, será mais trabalhosa do que o adequado para disciplina e precisa de revisão. Entretanto, a parte ‘free’ está clara e provavelmente será o suficiente para seu trabalho final. Se seguir nessa proposta, recomendo trabalhar apenas como 'free' e dar mais opções ao usuário. Por exemplo a opção de escolher se o diagrama vai ou não ter setas e se vai ou não ter o retângulo ao redor da palavra. A opção de iniciar a função sem saber quantas palavras e setas irá usar também seria interessante, para isso basta criar uma forma do usuário indicar que terminou de desenhar (por exemplo, depois de cada palavra/seta perguntar se já terminou ou talvez se clicar fora da área do gráfico) Considere fazer com que o tamanho da área do plot seja customizável ou dependa de quantas palavras o usuário pretende por. O argumento text precisa mesmo ser character? O nome dos nós de um diagrama podem ser números e é possível que o usuário envie fatores para usar como nome. Ao invés de parar a função, vale a pena converter o input do usuário em character e depois verificar se a conversão foi bem sucedida. Também não há a necessidade de parar a função porque o usuário enviou input que não será usado, basta emitir um aviso. O passo 6 e 7 são idênticos, não há porque separá-los, coloque a verificação da presença de 'text' dentro do seu loop. No passo 7.III.B, em vez de parar a função, basta pedir um input novo. --- //[[silasprincipe@usp.br|Silas Principe]] 2019/06/19 10:02// Renan, segue versão atualizada do projeto. Seguindo suas recomendações, utilizarei apenas a proposta do diagrama 'free'. Também alterei a escolha de cores, e dei a opção de ter ou não o retângulo. Agora há a opção de escolher o tipo de fonte. Não achei conveniente dar a opção de não inserir nenhum tipo de linha. Agora também há a opção de não inserir um vetor ''text'' e não especificar ''words''. Nesse caso o usuário terá um limite de 200 palavras, podendo parar quando desejar. ''text'' também pode ser um vetor numérico ou de fatores, sendo convertido para character na função. --- //[[delbel.renan@gmail.com|Renan Del Bel]] 2019/06/19 12:53// Está muito melhor! Tenho algumas pequenas sugestões, mas já está muito bom. A parte que roda quando text está presente e a parte que roda quando não está presente são praticamente idênticas. Isso é um bom indicativo que elas não precisam estar separadas. Ao invés de fazer um IF no começo da função que separa ela em dois caminhos totalmente independentes, pense no que acontece de diferente em cada opção e tente colocar IFs apenas para esses casos. Um pequeno detalhe: END é uma palavra razoavelmente comum para se colocar em um fluxograma. Eu pensaria em um sinal de parada que inclui caracteres especiais, apenas para ter menos chance de um usuário se frustrar, algo como /END ou Por fim, se você vai por um limite de 10 caracteres verifique antes se "text" cumpre esse requisito. Seria chato se a função parasse no meio, depois de você cuidadosamente posicionar a umas 15 palavras, porque seu input não estava adequado desde o inicio. Acho que é isso! ==== Proposta B: eatR ==== === Função para cálculo de receitas === \\ O desperdício de alimentos é um problema global. Dados da FAO indicam que 1/3 de todo o alimento produzido no mundo é perdido ou vai para o lixo[3]. Uma das formas de evitar o desperdício é cozinhar apenas o necessário para a refeição em questão. No entanto, aqueles que tem afinidade com a gastronomia sabem a dificuldade de reduzir ou aumentar receitas. Normalmente apenas se divide ou multiplica a receita original por dois, uma vez que encontrar valores intermediários é um exercício demorado. Assim, o objetivo dessa proposta é criar uma função que facilite o cálculo de receitas para uma quantidade //n// de pessoas considerando um tamanho de porção individual adequado para aquela receita. O resultado final é um //dataframe// contendo os ingredientes com as quantidades originais, o valor convertido e, no caso de receitas com ovos, um valor ajustado (uma vez que seria mais desperdício usar meio ovo). \\ \\ **Plano da função:** \\ \\ **Entrada:** eatR(rec, recipe, persons, portion, egg.w=60) '' rec '' = dataframe com duas colunas contendo 1) ingredientes (ing); 2) quantidades (qtt). No caso de um dos ingredientes ser ovo, o nome deve ser escrito em minúsculo, em português ou inglês, no singular. (classe: dataframe) \\ '' recipe '' = por padrão é NULL. Caso o usuário decida usar uma das receitas pré-definidas na função. Serão 4 opções a serem descritas no help. Ex: "pizza". (classe: character) \\ '' persons '' = quantidade de pessoas para as quais a receita deve ser calculada. (classe: numeric) \\ '' portion '' = valor da porção individual. O usuário deve estimar a quantidade que uma pessoa come daquela receita. (classe: numeric) \\ ''egg.w'' = opcional, por padrão é 60. Permite ao usuário definir, nos casos em que a receita apresenta ovo, qual o peso do ovo (classe: numeric). \\ \\ **Verificando os parâmetros** '' recipe '' está presente? Se sim, faz parte de uma das quatro receitas disponíveis? Se não, escreve "RECIPE deve ser uma das receitas pré-definidas."\\ '' rec '' está presente*? Se não, escreve "REC é necessário para o cálculo da receita". (*pode ser não caso '' recipe '' esteja presente). É um dataframe contendo uma coluna de nome "ing" (ingredientes) e outra "qtt" (quantidade)? Se não, escreve "REC deve ser um dataframe com duas colunas, uma de ingredientes (ing) e outra com as quantidades (qtt)". \\ '' persons '' está presente e é da classe numérica? Se sim, é maior ou igual a 1? Se não, escreve "PERSONS deve ser um número maior ou igual a 1". \\ '' portion '' está presente e é da classe numérica? Se não, escreve "PORTION deve ser um número". Adicionalmente, faz um teste para ver se o valor inserido é menor que 10 (uma porção improvável). Nesse caso apenas avisa "PORTION é um valor muito pequeno. Talvez necessite de revisão." \\ ''egg.w'': verifica se o valor é menor que 40 ou maior que 70[4] e apenas avisa "EGG.W muito pequeno/grande. Talvez necessite de revisão." \\ \\ **Pseudo-código** - Para caso '' recipe '' seja utilizado\\ - Cria quatro dataframes, cada um com uma das receitas pré-definidas (nome dos dataframes == nome da receita)\\ - Cria lista '' recipes '' com os quatro vetores\\ - Substitui objeto '' rec '' pela receita utilizada indexando a lista com o objeto '' recipe '' usando o código '' (recipes[ [as.name(recipe)] ] ''\\ - Se ovo estiver presente na receita\\ - multiplica o a quantidade de ovo na coluna '' qtt '' do objeto ''rec'' pelo valor do objeto ''egg.w''\\ - substitui o valor de ovo na coluna '' qtt '' pelo valor calculado\\ - Cria o objeto '' sum.tot '' com a soma do peso total da receita original somando os valores de ''qtt''\\ - Cria o objeto '' por.tot '' com o valor arredondado da divisão de ''sum.tot'' por ''portion''\\ - Cria a coluna ''conv'' no dataframe ''rec'' com os valores da coluna ''qtt'' multiplicados por ''persons'' e dividido por ''por.tot''\\ - Se ovo estiver presente na receita\\ - Cria o objeto ''eggs'' com o valor de ovo na coluna ''qtt'' e divide por ''egg.w'' para retornar em 'número de ovos'\\ - Cria o objeto ''e.round'' com o valor aproximado para o próximo inteiro (usando a função ceiling) de ''eggs'' dividido por ''eggs''. Isso dará um valor de correção\\ - Cria a coluna ''adj'' no objeto ''rec'' com os valores da coluna ''conv'' multiplicados por ''e.round''\\ - Substitui o valor de ovo na coluna ''adj'' pelo valor aproximado para o próximo inteiro (usando a função ceiling) de ''eggs''\\ - Transforma (e substitui) os valores de ovo nas colunas ''qtt'' e ''conv'' dividindo o valor ''por egg.w'' (retornando assim ao valor em número de ovos, e não peso)\\ - Arredonda os valores da coluna ''adj'' do objeto ''rec''\\ - Arredonda os valores da coluna ''conv'' do objeto ''rec''\\ - Imprime mensagem na tela com "Receita final:"\\ \\ \\ **Saída** - Retorna um dataframe com as colunas ''ing'', ''qtt'', ''conv'', e caso tenha ovos ''adj'' \\ \\ \\ --- //[[delbel.renan@gmail.com|Renan Del Bel]] 2019/06/13 12:53// Achei a ideia interessante, tenho algumas sugestões: Em primeiro lugar, em vez de incluir receitas prontas na sua função, deixe para usá-las no exemplo do help. Exigir que o data frame que você recebe tenha os nomes certos nas colunas não é necessário, já que você pode atribuir nomes se quiser ou trabalhar apenas com a indexação. Além disso, pense sobre como receitas normalmente são apresentadas: * Raramente todos os ingredientes têm a mesma unidade de medida, então somar esses valores e dividir por 'portion' não é interessante. * Por outro lado, muitas vezes é informado quantas porções ela serve. Então os argumentos 'persons' e 'portion' podem ser mudados para 'quantidade que a receita original' faz e 'quantidade que quero fazer'. Sobre os ovos: Não entendi direito como o cálculo foi feito: eggs/eggs será sempre igual a 1, não? Sugiro que deixe qtt de ovos ser em unidades. Com isso você já sabe quantos ovos por porção a pessoa vai usar e então não precisa mais de eggs.w. Mas eu permitiria deixar a pessoa escolher como arredondar o ovo. Talvez ela prefira diminuir a receita caso 'conv' tenha calculado que precisa de 6.1 ovos ou coisa assim. --- //[[delbel.renan@gmail.com|Renan Del Bel]] 2019/06/13 12:53// [editado: //2019/06/17 12:53//] Recomendo seguir com a proposta A, mas fazendo as mudanças indicadas. Tente reescrever o pseudo-código e colocar aqui embaixo (pode ser menos detalhado dessa vez, apenas para fecharmos o escopo de seu trabalho). Lembrando que o objetivo é que a função seja um desafio, então vamos conversando para acertar o nível de complexidade adequado. Casa tenha alguma dúvida ou comentário, pode entrar em contato por e-mail (delbel.renan@gmail.com) ou colocar aqui na página mesmo. ---- **Referências** [1] Bauer, M. I., & Johnson-Laird, P. N. (1993). How Diagrams Can Improve Reasoning. Psychological Science, 4(6), 372–378. https://doi.org/10.1111/j.1467-9280.1993.tb00584.x \\ [2] Marit M. Suttorp, Bob Siegerink, Kitty J. Jager, Carmine Zoccali, Friedo W. Dekker, Graphical presentation of confounding in directed acyclic graphs, Nephrology Dialysis Transplantation, Volume 30, Issue 9, September 2015, Pages 1418–1423, https://doi.org/10.1093/ndt/gfu325 \\ [3] http://www.fao.org/food-loss-and-food-waste/en/ \\ [4] http://www.uniquimica.com/2016/11/classificacao-de-ovos/ ==== Resultado final ==== === Proposta A === Página com o código da proposta A: [[.:visualR]] Página com o help da função: [[.:help visualR]]