Bioestatística com R – 3 – Inferência: teste t e ANOVA

Nesse terceiro tutorial, o objetivo é bem simples. Comparar duas populações usando o famoso teste t de Student e depois comparar outras três populações fazendo uma análise de variância (ANOVA).

Todas as tabelas usadas nos exemplos estão nessa pasta compartilhada.

Tutorial 1 – R como calculadora

Tutorial 2 – Usando e manipulando tabelas


Teste t

Pro teste t, vamos usar a mesma tabela do tutorial anterior, o clinical trial simulado (clinicaltrial.csv).

No anterior, vimos como filtrar e quebrar a tabela pra fazer análises. Agora faremos uma análise (o teste t) pra saber se existe uma diferença de melhora entre (1) homens e mulheres, (2) tratamento e placebo e (3) tratamento e placebo, mas só nos pacientes que fazem terapia. Note que isso não é uma sugestão de como é a análise correta a ser feita nesse caso, é só uma maneira de exercitar nossas habilidades em R.

Primeiro, precisamos importar os dados e criar a coluna de melhora:

ct.data = read.table("clinicaltrial.csv", sep=";", header = T)
wdata = ct.data %>%
 select(-age) %>%
 rename(before = scale.before, after = scale.after) %>%
 mutate(effect = after - before)

Pronto. Agora, o teste t. Existe em R uma função chamada t.test, que faz (adivinha!) testes t. Um jeito de usá-la, é passar duas colunas que você quer comparar. Assim:

data1 = wdata %>% filter(gender == "male")
data2 = wdata %>% filter(gender == "female")
t.test(data1$effect, data2$effect, alternative = "two.sided")

Uma observação: o “two.sided” também pode ser “greater” or “less”, dependendo do que você quer.

De graça, sem você pedir, R já mostra um resumo do resultado do teste. E se você quiser extrair valores específicos, tipo o valor de p ou do parâmetro t? Nesse caso, você precisa armazenar o resultado do teste em uma variável, pra poder extrair valores dela depois. O resultado é uma lista com vários valores relacionados ao resultado.

resultados = t.test(data1$effect, data2$effect, alternative = "two.sided")
resultados$p.value
[1] 0.216917

resultados$conf.int[1]
[1] -0.02688129

resultados$conf.int[2]
[1] 0.1181832

Agora, a segunda questão, a diferença entre placebo e controle.

data1 = wdata %>% filter(treatment == "SSRI")
data2 = wdata %>% filter(treatment == "Placebo")
t.test(data1$effect, data2$effect, alternative = "two.sided")

Por último, a diferença entre placebo e controle, mas só para os participantes que faziam terapia. Pra isso, precisamos filtrar a tabela antes pra pegar só esses casos. O resto é igual ao exercício anterior.

wdata = wdata %>% filter(doing.therapy)
data1 = wdata %>% filter(treatment == "SSRI")
data2 = wdata %>% filter(treatment == "Placebo")
t.test(data1$effect, data2$effect, alternative = "two.sided")

 

ANOVA

Pra esses testes, usaremos uma outra tabela, simulando um experimento de cultura de células tratadas com diferente substâncias. A tabela é cellculture.csv.

Importamos a tabela:

cc.data = read.table("cellculture.csv", sep=";", header = T)

As culturas foram tratadas com a substância A, substância B ou ambas (AB), em 9 replicatas, em dias diferentes. Queremos testar se existe diferença entre os tratamentos A, B e AB (todos expressos como porcentagem de viabilidade em relação ao controle).

Assim como pro teste t, existe uma função em R pra executar análises de variância e o nome é aov.

cc.data = cc.data %>% mutate(treatment = factor(treatment))
resultados = aov(data = cc.data, viability ~ treatment)
resultados
summary(resultados)

 

Isso não diz muito caso você queira saber quais tratamentos, em particular, são diferentes do controle. Pra isso, podemos usar o teste de Tukey, com a função TukeyHSD() nos nossos resultados de análise de variância.

TukeyHSD(resultados)

 

Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = viability ~ treatment, data = cc.data)

$treatment
           diff        lwr       upr     p adj
AB-A -25.940606 -37.742373 -14.13884 0.0000350
B-A    8.572924  -3.228843  20.37469 0.1864324
B-AB  34.513530  22.711763  46.31530 0.0000004

O resultado inclui, entre outras coisas, a análise pra cada par de tratamentos. Parece que a diferença entre A e B não é tão grande quanto a diferença entre AB e A ou B em separado.

Visualizando dados

Como adendo, vamos ver como fazer gráficos simples pra mostrar esses resultados.

Como exemplo, vamos pegar o clinical trial e plotar a diferença entre tratamento e placebo. Usaremos uma outra biblioteca, chamada ggplot2, pra fazer gráficos bonitos. Primeiro passo é instalar e carregar a biblioteca:

install.packages("ggplot2")library(ggplot2)

Agora, fazer os gráficos. A função simples pra fazer gráficos se chama qplot. Veja o exemplo (e o gráfico resultante), pra se motivar a entender como funciona. Carregamos os dados antes:

ct.data = read.table("clinicaltrial.csv", sep=";", header = T)
wdata = ct.data %>%
 select(-age) %>%
 rename(before = scale.before, after = scale.after) %>%
 mutate(effect = after - before)

Plotando:

qplot(data = wdata, x = treatment, y = effect)

Isso é o básico. Você diz qual é a tabela (data) e o que o x e o y representam (que colunas da tabela). Assim já dá pra visualizar, mas é fácil deixar mais interessante.

qplot(data = wdata, x = treatment, y = effect, geom = "boxplot")

Nesse, especificamos que geom deve ser usado (no caso, pedimos um boxplot). Se você não especifica nada, ele usa pontos (como no gráfico anterior).

E se quiséssemos colorir os pontos, dependendo da pessoa fazer ou não terapia?

Basta especificar que a cor (color) vai ser de acordo com a coluna da terapia. E sim, ele faz a legenda sozinho pra você.

Agora, parece que as pessoas com e sem terapia estão mais ou menos separadas (os pontos azuis tendem a estar mais pra cima). Podemos separar os gráficos de um jeito simples, usando facets.

Os facets separam o gráfico de acordo com uma coluna: o da esquerda é pra quem não faz terapia, o da direita pra quem faz.

Uma vez que o gráfico é satisfatório, o resto é estética. Primeiro, agora vamos armazenar o gráfico numa variável (escolhi p, de plot). E no código abaixo, são alterados, respectivamente: título, nome do eixo X, nome do eixo Y e a legenda de cada gráfico. Não se preocupe tanto com a maneira de mudar cada coisa, pra entender porque teríamos que nos aprofundar mais sobre o “jeito ggplot de construir gráficos”, o que daria todo um novo conjunto de tutoriais (ou livros, como esse, do próprio criador).

Note o sinal de + no final de cada linha (pense que estamos adicionando detalhes ao plot). Note também que antes é necessário criar uma nova coluna pra servir de rótulo compreensível pra terapia/sem terapia.

wdata = wdata %>% mutate(rotulo.terapia = ifelse(doing.therapy, "Com Terapia", "Sem Terapia"))
p = qplot(data = wdata, x = treatment, y = effect, facets = ~rotulo.terapia, geom = "boxplot") +
 labs(title = "Figura 1. Efeito do tratamento com a droga", x = "Efeito", y = "Tratamento")
 
p

Viu? Agradável ao olhar. :)


E é isso. O workflow básico tá estabelecido. Importar os dados, preparar os dados, fazer análises (que podem ser qualquer outra, não necessariamente essas feitas aqui) e visualizar as conclusões.

Bioestatística com R – 2 – Usando e manipulando tabelas

Nesse segundo tutorial, o foco é em importação e exportação de dados pra arquivos, além de como fazer as manipulações mais comuns nas suas tabelas: filtrar de acordo com critérios, criar, renomear e remover colunas, extrair resumos dos dados, entre outras coisas mais.

Todas as tabelas usadas nos exemplos estão nessa pasta compartilhada.

Tutorial 1 – R como calculadora


Importando e exportando dados

Vamos começar do que é mais direto. Digamos que você tem um conjunto de dados que quer salvar num arquivo. Pra fins de armazenamento de dados nesse tutorial, vamos usar arquivos CSV (comma-separated values, de valores separados por vírgulas). Esses arquivos são arquivos texto normais, onde cada linha do arquivo vira uma linha da tabela e as colunas são separadas por vírgulas (ou qualquer outro caractere, digamos, ponto-e-vírgula).

Então, podemos criar um conjunto de dados arbitrário em R. Conjuntos de dados são armazenados em variáveis do tipo data.frame. Pra criar um, você pode usar vetores como colunas:

numeros = c(1,2,3)
letras = c("a","b","c")
uns.dados = data.frame(
 coluna1 = numeros,
 coluna2 = letras
)
uns.dados

Se tudo deu certo, apareceu uma tabelinha, de 3 linhas, com os dados, embaixo de cada coluna tem o tipo da coluna (dbl pra double, o termo para números não-inteiros, com decimais e fctr pra caracteres/strings).

Agora, pra salvar esses dados:

write.table(df, "uns dados.csv", sep = ";", row.names = F)

De novo, tudo dando certo, deve existir um arquivo chamado uns dados.csv na mesma pasta do seu arquivo R. Quem fez tudo foi a função write.table.

A primeira coisa que você passa pra função write.table é o seu data.frame. Em seguida, o nome do arquivo (pode colocar a pasta e o resto do caminho se quiser salvar em outra pasta). Depois sep indica o caractere que separa as colunas. O “normal” é usar vírgula mesmo, como diz o nome do arquivo. Mas aqui no Brasil, por exemplo, a vírgula é usada pra separar as casas decimais, o que pode confundir na hora de ler o arquivo (em inglês, usa-se o ponto, então não é problema). Por isso eu prefiro usar ponto-e-vírgula sempre que dá. O último argumento, row.names, está colocado como FALSE, só pra que R não numere as linhas (esse seria comportamento dessa função se você colocasse TRUE ou não dissesse nada).

E se quisermos agora abrir o arquivo que acabamos de salvar? A lógica diria que existe uma função inversa, read.table que lê arquivos, mais ou menos nos mesmos moldes. O argumento header diz pra função que a primeira linha da tabela é o “cabeçalho”, contendo os nomes das colunas.

dados.lidos = read.table("uns dados.csv", sep = ";", header = T)
dados.lidos

E voilá. Você diz o nome e onde está o arquivo e qual o caractere que separa colunas e pronto! Agora faremos operações sobre os dados.

Descrevendo os dados

Primeiro, a gente tem que usar o que vimos ainda agora pra obter dados mais interessantes do que esses inventados.

A tabela que usaremos pode ser baixada aqui: clinicaltrial.csv

Essa tabela tem dados inventados e simplificados sobre um clinical trial de uma droga pisquiátrica qualquer. Ele possui 6 colunas:

  • gender: masculino/feminino
  • treatment: grupo placebo ou droga ativa (SSRI – Selective Serotonin Reuptake Inhibitor – uma classe de drogas psiquiátricas)
  • age: idade
  • doing.therapy: se a pessoa está ou não fazendo terapia ao mesmo tempo
  • scale.before: severidade do transtorno antes do tratamento, medida por uma escala
  • scale.after: severidade do transtorno ao final do tratamento, medida pela mesma escala

O objetivo aqui é aprender a extrair médias e medianas, desvios e variâncias, pra diferentes subgrupos.

Tem umas coisas que precisamos saber antes. Primeiro, carregamos a tabela (lembre-se que pra funcionar, a tabela tem que estar na mesma pasta do notebook, senão você precisa dizer a pasta também, o caminho inteiro, e não só o nome do arquivo):

ct.data = read.table("clinicaltrial.csv", sep=";", header = T)
summary(ct.data)

A função summary dá um resumo da tabela, útil pra checarmos se saiu tudo direitinho. Por exemplo, são 297 mulheres e 324 homens, idades vão de 22 a 45 e o valor na escala antes do estudo varia de 4 a 10, com média 7,129.

Agora, e se quisermos armazenar a média das idades em uma variável? Pra extrair uma coluna de uma tabela, usamos o símbolo $.Porexemplo, ct.data$age te dá a lista de valores da coluna age. E R possui uma função mean() que calcula médias (e várias outras).

mean(ct.data$age)

Nada muito diferente se quisermos a mediana, o desvio padrão ou a variância.

median(ct.data$age)
sd(ct.data$age)
var(ct.data$age)

dplyr

Agora, pra complicar um pouco. E se quisermos a média de idade só pra mulheres? Pra esse tipo de tarefa, podemos proceder de alguns jeitos diferentes. Aqui, usaremos uma biblioteca chamada dplyr.

Uma biblioteca é um pedaço de código em R, um conjunto de funções e outras coisas úteis que são agrupadas pra serem usadas como um pacote: dplyr contém funções pra manipulação de data.frames, em outro momento usaremos um outro pacote pra fazer gráficos, etc. Existem muitos muitos pacotes, pra coisas bem específicas e todo tipo de análise, feitos por pessoas de todo o planeta. Esse é um dos pontos fortes de R.

Pra instalar dplyr (ou qualquer outra biblioteca):

install.packages("dplyr")

Uma vez instalado, sempre que for usar, você precisa importar a biblioteca (ignorem os avisos que vão aparecer):

library(dplyr)

O que dplyr nos dá é um operador novo e um conjunto de funções úteis. Por exemplo, as que usaremos hoje:

  • a função mutate, pra adicionar colunas;
  • a função rename, pra renomear colunas;
  • a função filter, pra selecionar só algumas linhas da tabela de acordo com critérios;
  • a função select, pra gerar uma nova tabela só com algumas colunas selecionadas;
  • a função group_by, pra separar uma tabela em subtabelas seguindo algum critério;
  • a função summarise, pra gerar medidas descritivas de conjuntos de dados (tipo média, desvio, etc);
  • o operador %>%, pra passar tabelas pras funções ou pegar o resultado de uma função e passar pra seguinte.

As descrições acima são só pra referência, veremos uma por uma agora.

Manipulando dados

Voltemos ao problema anterior: queremos a média de idade das mulheres no estudo.

Esse é um trabalho pra função filter. Veja uma maneira de usar:

mulheres = ct.data %>% 
 filter(gender == "female")
media.idade.mulheres = mean(mulheres$age)
media.idade.mulheres

[1] 33.74411

Intuitivo? Primeiro, criamos uma nova tabela, mulheres, que contém só as mulheres da tabela original. Isso é obtido com dplyr: os dados originais (ct.data) são passados (com %>%) pra função filter, que usa como critério o gênero (coluna gender) ser igual a (==) “female”. Depois é só calcular a média das idades, como antes.

Legal. Mais complicado. E se quisermos a idade média das mulheres que faziam terapia? E das que não faziam? Tente você mesmo antes de ver como fazer abaixo (basta usar os operadores lógicos que vimos antes: E, OU, NÃO)

mulheres.terapia = ct.data %>% 
 filter(gender == "female" & doing.therapy)
mulheres.nao.terapia = ct.data %>% 
 filter(gender == "female" & !doing.therapy)


mean(mulheres.terapia$age)
[1] 33.93396

mean(mulheres.nao.terapia$age)
[1] 33.63874

Ok. Agora, digamos que estamos interessados só nas escalas, não mais na idade. Então quero uma tabela nova que não tenha a coluna de idade. Pra isso, a função select é o que queremos.

wdata = ct.data %>%
 select(gender,treatment,doing.therapy,scale.before,scale.after)
wdata = ct.data %>%
 select(-age)
names(wdata)

O que aconteceu acima: pra função select, você pode especificar que colunas quer manter ou que colunas quer remover (com o sinal de menos). A função names diz que colunas existem, só pra checar se deu certo. E o nome da variável é wdata de working data, os dados de trabalho, que estão em uso nesse momento (é só um nome que eu uso sempre quando falta um nome melhor).

Agora, imagina que você não gosta dos nomes das colunas de escalas, quer mudar só pra before e after. Pra isso, a função rename existe.

wdata = ct.data %>%
  rename(before = scale.before, after = scale.after)
names(wdata)

Próxima etapa. Queremos uma coluna nova – effect -, que indique a melhora do paciente no período, medido pela escala, ou seja, o valor da escala depois menos o valor da escala antes. A função mutate faz isso (o nome é porque ela muda, transforma a forma da tabela):

wdata = wdata %>%
 mutate(effect = after - before)

Agora dá pra mostrar uma coisa que deixa dplyr muito mais divertida. Você pode encadear várias funções. O que fizemos em três partes acima, pode ser feito de uma vez só:

wdata = ct.data %>%
 select(-age) %>%
 rename(before = scale.before, after = scale.after) %>%
 mutate(effect = after - before)

O código acima é equivalente ao que fizemos antes.

Agora a gente tem a tabela nova, podemos voltar a extrair médias (ou qualquer outra medida), como antes. Por exemplo, qual a melhora média das melhora média das mulheres que fazem terapia ou tinham a escala >= 8 antes do estudo?

subdata = wdata %>%
 filter(gender == "female" & (doing.therapy | before >= 8))
mean(subdata$effect)

Ótimo. Última coisa. Todos essas médias que calculamos pra subgrupos específicos podem ser feitas de um jeito mais interessante, usando as funções group_by e summarise. A ideia é quebrar a tabela em grupos de acordo com algumas colunas e calcular alguma coisa pra cada grupo, devolvendo os resultados já sumarizados numa tabela nova.

Exemplo. Digamos que queremos a média da melhora pra cada sexo.

medias = wdata %>%
  group_by(gender) %>%
  summarise(media = mean(effect))
medias

O resultado é uma tabela nova, que contém uma coluna pro sexo e outra pro resultado da média, que criamos na função.

E se quisermos, além de separar por sexo, saber também as médias pra grupos placebo/tratamento ativo? E se quisermos saber também o desvio padrão, além da média?

medias = wdata %>%
  group_by(gender, treatment) %>%
  summarise(media = mean(effect), desvio = sd(effect))
medias

Pronto. Nova tabela, com os resultados pra cada grupo.


É isso. Vimos como importar tabelas, usamos e abusamos de dplyr pra fazer o que quiser com os dados pra prepará-los pra análise (aqui só calculamos médias, mas vamos fazer algo mais sofisticado em breve).

Bioestatística com R – 1 – R como Calculadora

        Nesse primeiro tutorial, pra se acostumar com R e com o RStudio, a ideia é fazer contas e operações básicas. Nada de estatística por enquanto. Um passinho de cada vez (esse texto assume que você tem R e RStudio instalados e funcionando no seu sistema … se não for o caso, veja aqui como instalar).

Notebooks

Primeira coisa é abrir o RStudio e criar um notebook (File > New File > R Notebook).

Notebooks são arquivos em que você pode misturar texto formatado e de exposição com código em R, executável. É ideal pra registrar as suas análises de um modo reprodutível. Você pode criar explicações entre os trechos de código, assim o resultado é o código funcional e já documentado, ótimo pra relatar a análise pra outras pessoas (e pra fazer tutoriais).

Pronto, notebook criado. Ele já contém algum texto, explicando o básico de como usar um notebook. O que você precisa saber agora é que qualquer código tem que estar dentro de um bloco de código. Pra inserir um bloco de código, o atalho é Ctrl + Alt + I.

Apague o conteúdo que já veio no arquivo – exceto as 4 primeiras linhas, que especificam o título e o output. Mude o título como preferir (lembre que ele deve estar entre aspas).

R como Calculadora

Agora crie o primeiro bloco de código com o atalho (Ctrl + Alt + I). Digite o código abaixo no bloco de código criado.

# Variável a
a = 5
a

Ele deve mostrar [1] 5. O que essas duas linhas de código fizeram?

a = 5

Cria uma variável a e armazena o valor 5 nela. Uma observação importante: o símbolo de igual = e a setinha pra esquerda <- são equivalentes em R. Significam algo como “armazene a coisa à direita na coisa à esquerda”.

a

Isso faz com que o R te mostre o valor de a, que no caso é 5, porque fizemos isso na linha de cima.

# Variável a

Essa linha não faz nada. Como ela começa por #, ela é um comentário. Comentários (qualquer linha iniciada por #) são ignorados pelo R, só servem pra nós, humanos. Comentar o seu código de maneira informativa é um excelente hábito pra um programador. Primeiro, pra ajudar outras pessoas que venham a ler e tentar entender o seu código. Segundo, pra você mesmo se entender … não importa o quão claro e auto-explicativo seja o seu código, se você ficar dois dias sem vê-lo você vai esquecer o que estava pensando na hora.

Ok. Então você sabe como criar variáveis. Agora, façamos operações com elas.

# Operações
b = 3
c = a + b
c

Bom, tente adivinhar o que isso vai mostrar.

A resposta é 8. Coisas importantes aqui: (1) R não esquece facilmente. O valor de a que atribuímos antes ainda está lá. (2) Operações funcionam como se imaginaria. As quatro básicas são +, -, * e /. (3) Experimente. Veja os exemplos abaixo.

# Operações básicas
a * 5
[1] 25

b + 10
[1] 13

c / 2
[1] 4

c / 3
[1] 2.666667

2 * (a + b + c - 1)
[1] 30

# Potência
a ^ 2 # 5 ao quadrado
[1] 25

R não se limita a operações aritméticas básicas, é claro. Você também pode aplicar funções, várias já existem em R sem você precisar fazer nada.

cos(360)
[1] -0.2836911

cos(2*pi)
[1] 1

tan(pi/4)
[1] 1

log(10)
[1] 2.302585

log10(10)
[1] 1

Note que: (1) cosseno de 360 não é 1 … Por que? R assume que você está dizendo ângulos em radianos, não em graus. (2) Teste calcular o seno de pi radianos (180º) ou a tangente de pi/2 radianos (90º). Tente entender o que significa o resultado. (3) A função log() usa como base a constante de Euler (e). Pra calclular com base 10, exsite outra função: log10().

Juros compostos

Podemos tentar fazer coisas mais sofisticadas agora. Digamos que você tem um problema clássico de livro-texto, sobre juros compostos.

Você recebeu R$ 10.000,00 e investiu num fundo com rendimento de 5% ao ano, por 10 anos. Qual a soma total no final dos 10 anos?

inicial = 10000 # R$ 10.000,00
juros = 5 / 100 # 5%
tempo = 10 # 10 anos
final = inicial * (1 + juros) ^ tempo
final

[1] 16288.95

E se for por 20 anos? E se começar com metade do dinheiro? E se os juros triplicarem? A graça é que agora basta mudar uma linha do código acima pra chegar no novo resultado.

Outros tipos de variáveis

Além de números, variáveis em R também podem armazenar caracteres e palavras (além de objetos mais complexos, como tabelas e dados … mas fica pra depois). Esses caracteres, do tipo string, são sempre colocados entre aspas:

palavra = "tutorial"
palavra

[1] "tutorial"

Outro tipo importante é o tipo lógico. Variáveis desse tipo só podem ter dois valores: TRUE ou FALSE (também pode ser T e F). E eles tem as próprias operações. Por exemplo, imagine duas variáveis:

         chuva: que diz se está chovendo

         guardachuva: se eu tenho um guarda-chuva molhado: diz se eu vou ficar molhado

Eu só fico molhado se estiver chovendo E se eu NÃO tiver guarda-chuva. Ou, em outras palavras, eu fico seco (NÃO molhado) se NÃO estiver chovendo OU se eu tiver guarda-chuva.

Agora, em R, o símbolo & representa E, o símbolo | representa OU e o símbolo ! representa NÃO.

Expresso em R, isso fica assim:

chuva = TRUE
guardachuva = FALSE
molhado = chuva & !guardachuva
seco = !chuva | guardachuva
molhado

[1] TRUE

Teste mudar os valores de chuva e guardachuva pra ver se ficamos molhados ou secos.

Vetores

Uma última coisa, pra começarmos a entender a graça de R.

Além de variáveis que armazenam um único valor (seja ele um valor numérico, string/caracteres ou lógico ou qualquer coisa), também existem variáveis que armazenam conjuntos de valores. Existem vários tipos de “conjuntos”, mas por enquanto falaremos só dos vetores, que armazenam vários objetos do mesmo tipo (qualquer tipo, desde que todos do mesmo).

Vetores são criados com a função c() (c de combine). Exemplos:

v = c(1,2,3)
w = c(a,b,s)
sudeste = c("RJ","SP","ES","MG")
logicos = c(TRUE,FALSE,FALSE,TRUE,FALSE)

Bem legal e tal … mas e daí? E daí que você pode fazer operações em vetores. Qualquer coisa que você faz em um objeto único, isolado, você pode fazer em vetores. R entende, em geral, que você quer fazer aquilo com cada um dos elementos do vetor.

Por exemplo. Digamos que eu tenho vários números que eu quero elevar ao quadrado. Podemos fazer como antes:

n1 = 3
n2 = 20
n3 = 5

n1 ^ 2
n2 ^ 2
n3 ^ 2

[1] 9
[2] 400
[3] 25

Legal. E usando um vetor?

n = c(3,20,5)
n ^ 2

[1] 9 400 25

Problema: na minha pequena empresa eu tenho 3 funcionários, que ganham R$ 2000, R$ 1500 e R$ 1200. Quero dar um aumento de 10% pra cada um. Quanto vou pagar de salário com esse aumento?

salarios = c(2000,1500,1200)
salarios.com.aumento = salarios * 1.1
salarios.com.aumento

[1] 2200 1650 1320

Temos os salários pós-aumento. Mas e se eu quiser a soma deles? Bom, como são só três, você poderia fazer de cabeça ou no papel. Mas, a proposta aqui é exatamente deixar o R fazer isso por você. Convenientemente, existe uma função que soma todos os valores de um vetor, o nome é sum(vetor).

(PARÊNTESES SOBRE FUNÇÕES: funções recebem alguma informação sua e devolvem outra. A informação recebida é o conjunto de argumentos da função, que vem entre aprênteses depois do nome. É exatamente como no seno e cosseno ou log. A função sin(angulo) recebe um número, que ela interpreta como um ângulo em radianos e retorna o valor do seno desse ângulo. Ela recebe um número e retorna um número. A função sum(vetor) é um pouco diferente. Ela recebe um vetor de números e retorna um número (a soma dos números contidos no vetor). E existem inúmeras outras funções muito mais complicadas que essas e você pode criar as suas próprias funções também! Em outro momento …)

Então, parênteses fechado, você pode saber o total rapidamente:

total = sum(salarios.com.aumento)
total

[1] 5170

E a diferença entre o gasto antes e depois do aumento?

diferenca = sum(salarios.com.aumento) - sum(salarios)
diferenca

[1] 470

Última coisa. Imagina que você quer saber quantos dos funcionários ganharão mais do que dois salários mínimos após o aumento.

salario.minimo = 937
ganham.mais = salarios.com.aumento > salario.minimo * 2
ganham.mais
[1] TRUE FALSE FALSE

O resultado é TRUE, FALSE, FALSE. Quer dizer que R já fez as comparações, uma por uma, e reportou. E só um dos funcionários (o primeiro) ganhará mais do que dois salários mínimos.


Espero que isso dê uma amostra do que dá pra fazer com R. Especialmente esse final, a naturalidade com que R faz operações com vetores, é importante pra R ser útil e divertido.

Sobre jogos educativos

“I can sum up educational games in one word – and that word is… CRAP!”
Brenda Lauren

A maior parte dos jogos educacionais não são divertidos ou educativos. Digo maior parte, porque existem exceções e a frase acima é ligeiramente exagerada. O problema principal é que eles fazem algo que outros meios (material escrito, audiovisual, aulas) poderiam fazer. Talvez pior, porque os outros meios nem sempre tem a expectativa de serem divertidos (não que isso seja um ponto forte dos outros meios … ninguém devia se orgulhar de ser chato ou entediante … mas ninguém aborda uma oportunidade de fazer exercícios num livro-texto com a expectativa de que vai ser uma experiência muito divertida).

Tipos de uso de jogos para educação

Saindo da ideia mais específica de “jogos que educam” pra “como jogos podem ser usados em educação”, existem diversas maneiras de usar jogos como ferramentas de aprendizado. Penso que parte do problema é que na maior parte do tempo a gente pensa só em um desses tipos, e ainda pensa no que é menos interessante.

Minha escolha de classificação aqui é dividir os jogos pelo foco dado ao conteúdo educativo, pela posição onde ele aparece em relação ao gameplay e às mecânicas centrais pro jogo. Isso em grande parte determina como o jogo pode ser usado pra apoiar o aprendizado. Sendo assim, eu os classificaria em quatro tipos, descritos abaixo:

Frontal

Eu ia chamar de jogos explícitos, mas preferi mudar pra frontal (que sim, também tem conotações parecidas). Jogos onde o conteúdo é frontal são os jogos que são claramente desenvolvidos com o propósito de serem educativos, acho que é isso que vem à mente se alguém fala em “jogos educativos”. Exemplo escolhido aleatoriamente na categoria Educacional da Play Store: Math Games pra Android. Algo que você poderia fazer no papel sem perder nada. Colocar pontos e recordes não muda muito a experiência. Jogos de responder perguntas, de trívia também se encaixam aqui, jogos que são essencialmente provas de múltipla escolha, mas com medalhas. A maior parte dos esforços de gamificação pra mim cabem aqui também.
Nessa categoria eu também coloco jogos que possuem um plot desconectado do conteúdo. O cachorro precisa atravessar o lago: resolva essa equação pra ajudá-lo. O mago precisa de mana pra poder usar feitiços: responda essa pergunta pra gerar mana. Um exemplo engraçado disso é esse jogo pra Android que se passa no Rio de Janeiro: Detetive Carioca 2. Você “ataca” os monstros respondendo a perguntas de conhecimentos gerais (não é educativo, mas demonstra o tipo de jogo a que me refiro).

O problema desses jogos é que não tem nada que o jogo faça que outro meio não pudesse fazer (com custo menor, aliás). Eles acabam sendo chatos. Parecem uma desculpa pra dizer que você está fazendo algo educacional. A parte educativa do jogo parece ser um afterthought e não algo pensado e construído pra ser parte fundamental do design. No final são um exercício repetitivo, não funcionam nem como jogo nem como ferramenta educativa.

Incorporado

Meu exemplo favorito aqui é Carmen Sandiego, da década de 80, que gerou o desenho de mesmo nome. O progresso no jogo, de uma maneira mais ou menos natural, dependia de conhecimento de geografia e história para saber pra onde os criminosos iriam em seguida. E o conhecimento era obtido fora do jogo: eu me sentia um pesquisador, com dicionário, atlas e livros de história e geografia em volta do computador pra serem consultados conforme a necessidade (eu jogava isso numa era pré-Google, claro).
Nesse tipo de jogo o gameplay é o motivador, apenas. Ele gera a necessidade de ter o conhecimento, você vai atrás dele pelos seus meios (ele pode ou não estar contido no próprio jogo). O progresso no jogo não depende exclusivamente desse conhecimento, existem outras mecânicas (em Carmen Sandiego, por exemplo, você tem que administrar o tempo que tem pra investigar, usar a informação sobre a suspeita pra gerar o mandado de prisão, etc).
Esses parecem um passo adiante em relação aos jogos de conteúdo frontal. Em particular, eu nunca me dei conta que Carmen Sandiego era um jogo educativo quando jogava. Era “só” divertido, na minha percepção. E até hoje eu sei identificar bandeiras obscuras.

Periférico

Jogos onde o conteúdo é periférico, tangencial ao jogo. Nesse caso, os jogos não funcionam como ferramentas auto-suficientes. Eles são apenas o gancho pra motivar uma discussão. Aqui não necesariamente estamos falando de jogos pensados como “educativos”. Qualquer jogo pode ser usado, muito como filmes são usados pra servir de iniciador de reflexões sobre algum tema. Especialmente numa época em que temos toda uma indústria de jogos cinemáticos e com foco na narrativa, isso se torna muito mais viável. Assim como Avatar ,do James Cameron, pode ser usado pra motivar uma discussão sobre interfaces cérebro-máquina, um jogo como Assassin’s Creed pode ser usado pra motivar discussões sobre a Revolução Francesa ou Americana.
Nesse caso, é fundamental ter o professor conduzindo a atividade. Isso é reforçado pela evidência de que ferramentas digitais em sala de aula funcionam melhor quando não são auto-contidas (meta-meta-análise de John Hattie). Esse é o tipo de jogo que funciona bem em conjunto com outras atividades, exigindo planejamento pra incorporar esse tipo de atividade no currículo, o que me parece um benefício colateral.

Nas mecânicas

Esse é pra mim o santo graal dos jogos educativos. Todo jogo é educativo, no sentido de que um jogo bom é capaz de ensinar regras complexas, passar instruções longas e fazer os jogadores entenderem sistemas complexos sem nem perceber, engajados o tempo todo, se divertindo, até dominarem completamente o modo de ação dentro daquele sistema. Um bom jogo vai ensinar as mecânicas *e* vai ser divertido. A conclusão natural é que se você quer aproveitar bem os jogos pra ensinar alguma coisa, o conteúdo tem que estar nas mecânicas, entremeado com o gameplay, com o “jogar bem”. O jeito mais simples de fazer isso me parece ser através de simulações, mas não necessariamente o gênero “Simulação” (como The Sims ou SimCity). Simulações no sentido de qualquer que seja a habilidade a ser aprendida ou o sistema a ser entendido, o jogo reproduza aspectos do processo real, mesmo que simplificado. Claro que isso limita o designer a fazer jogos que ensinem procedimentos, processos, sistemas, maneiras de pensar, resolução de problemas, etc. Isso exclui certas coisas, que envolvem a memorização e retenção de muitos conceitos (anatomia, por exemplo). Mas esse tipo de conteúdo é o tipo que pode ser passado sem usar jogos, de maneiras mais baratas e efetivas, deixando pros jogos aquilo que eles fazem bem.
No final, SimCity funciona bem pra causar reflexões sobre o que a administração de uma cidade exige e existem projetos usando o jogo com esse propósito. Democracy é um ótimo jogo pra pensar sobre governo e política. Plague Inc é excelente pra ganhar intuições sobre epidemiologia. E pra sair das simulações assim classificadas como gênero, DragonBox ensina álgebra e manipulação de frações pra crianças sem falar em números, usando simplesmente uma roupagem nova pros símbolos.
Jogos assim funcionam como jogos, simplesmente. Aprender e jogar se tornam sinônimos. Esse argumento de uma forma mais completa é feito no livro Learning as Fun, de um ex-funcionário da Rovio (estúdio famoso por Angry Birds) que agora com seu próprio estúdio de desenvolvimento de jogos pretende colocar isso em prática. O estúdio, Lightneer lançou o primeiro jogo há pouco tempo, Big Bang Legends, sobre elementos químicos (ainda não joguei).

Conclusão

Minha apresentação vai em ordem crescente de “bom uso de jogos como ferramentas de aprendizado” (embora o primeiro tipo seja o único que eu considero “mau uso”). Eu evitei falar de gamificação da educação, isso fica pra outro momento (acho que tem coisas a serem aprendidas com a capacidade de jogos de engajar e de motivar, mas parece que o que leva o nome de gamificação não tá indo nesse caminho). Meu ponto é que fazer um jogo, como quer que seja, só pra substituir exercícios de livro-texto ou a exposição de um conteúdo é uma má ideia, no mínimo um uso não cuidadoso dos seus recursos (desenvolver jogos dá trabalho). E que ao fazer jogos educativos a gente tem que lembrar que eles são jogos, que eles tem que ser divertidos, tem que ter um bom design, tem que engajar, levar ao flowalém de serem educativos de alguma forma. Ser divertido é pré-requisito pra ser educativo, não é opcional, não é um extra.