Uma Introdução à Programação com o R

Jessica Kubrusly

Objetos no R

Números

Podemos usar o R como uma calculadora.

5 + 4
[1] 9
3 * 2
[1] 6
( 1.4 - 2*(3+10.1) )/20
[1] -1.24

Números

Podemos usar o R como uma calculadora.

exp(2)
[1] 7.389056
log(10)
[1] 2.302585
sin(pi)
[1] 1.224606e-16
cos(pi)
[1] -1

Números

E podemos atribuir valores às variáveis locais e realizar operações a partir delas.

x = 5

O objeto x guarda o valor 5.

x + 4
[1] 9
x^2
[1] 25
(2*x - 1)/3
[1] 3
log((2*x - 1)/3)
[1] 1.098612

Caracteres

O R também pode trabalhar com texto.

a = "oi"
a
[1] "oi"
b = "com vai?"
b
[1] "com vai?"

Caracteres

Ele tem operadores especiais para isso.

paste(a,b)
[1] "oi com vai?"
paste(a,", ",b)
[1] "oi ,  com vai?"
paste0(a,", ",b)
[1] "oi, com vai?"

Lógicos

Em muitas situações precisamos de operadores lógicos, e no R eles são:

  • T ou TRUE
  • F ou FALSE

Lógicos

Estes objetos aparecem como respotas para testes lógicos.

3 < 2
[1] FALSE
2 == 2.0
[1] TRUE
2 != 2.0
[1] FALSE
x >= 0
[1] TRUE

Lógicos

Também temos operadores para os objetos lógicos: & e |.

(3==4) & (2>=1)
[1] FALSE
(3==3) | (2>=1)
[1] TRUE

Vetores

Os vetores são uma estrutura de dados importante em qualquer linguagem de programação. Eles podem armazenar:

  • números,
  • caracteres,
  • elementos lógicos,
  • entre outros objetos, desde que sejam do mesmo tipo.

Vetores

No R a função c concatena objetos do mesmo tipo como vetores.

y = c(2,3,4,5,6)
y
[1] 2 3 4 5 6
texto1 = c("A","AA","ABB")
texto1
[1] "A"   "AA"  "ABB"
logico = c(F,F,T)
logico
[1] FALSE FALSE  TRUE

Vetores

A função c também concatena vetores de um mesmo tipo em um único vetor.

x;y
[1] 5
[1] 2 3 4 5 6
z = c(x,y)
z
[1] 5 2 3 4 5 6

Vetores

Isso vale para qualquer vetor de qualquer natureza.

texto2 = c("1","2","3","4","5","6")
c(texto1,texto2)
[1] "A"   "AA"  "ABB" "1"   "2"   "3"   "4"   "5"   "6"  
ab = c(a,b)
ab
[1] "oi"       "com vai?"

Vetores

As operações feitas entre objetos de um certo tipo também podem ser realizadas entre vetores do mesmo tipo.

y
[1] 2 3 4 5 6
y + 4
[1]  6  7  8  9 10
z
[1] 5 2 3 4 5 6
y + z
[1]  7  5  7  9 11  8

Vetores

texto1
[1] "A"   "AA"  "ABB"
paste(texto1,"0")
[1] "A 0"   "AA 0"  "ABB 0"

Vetores

logico
[1] FALSE FALSE  TRUE
logico & TRUE
[1] FALSE FALSE  TRUE
logico & c(TRUE,FALSE,FALSE)
[1] FALSE FALSE FALSE
logico | TRUE
[1] TRUE TRUE TRUE
logico | c(TRUE,FALSE,FALSE)
[1]  TRUE FALSE  TRUE

Funções

Uma ferramenta importante no R é a criação de funções.

nome_da_funcao = function(argumento1,argumento2){
  # aqui colocamos a operacao que queremos realizar com os valores passados 
  # como argumentos de entrada
  saida = (argumento1 + argumento2 + 10)/2
  #o comando return defini o que a funcao retorna
  return(saida)
}
nome_da_funcao(3,4)
[1] 8.5

Problemas

Vamos trabalhar esses conceitos e outros com problemas práticos.

Investimento

Suponha que eu tenha R$1.000,00 para investir na poupança, que rende 0,5% ao mês. Como posso usar o R para saber o montante que terei aplicado depois de 3 anos?

Problema - Investimento

Como se faz essa conta?

\[ \begin{array}{lcll} v_0 &=& 1000\\ v_1 &=& 1000 + (0,5/100) \times 1000 = 1005\\ v_2 &=& 1005 + (0,5/100) \times 1005 = 1.010,025\\ &\vdots& \end{array} \]

Problema - Investimento

Usando o computador para repetições: for.

for(vec in valores){
  tarefas para serem executadas  
}

Problema - Investimento

Qual o montante que aplicado depois de 3 anos?

valor = 1000
for(i in 1:36){
  valor = valor + valor*0.5/100
}
valor
[1] 1196.681

Problema - Investimento

E depois de 10 anos?

valor = 1000
for(i in 1:120){
  valor = valor + valor*0.5/100
}
valor
[1] 1819.397

Problema - Investimento

E se o investimento inicial for de R$900,00 em vez de R$1.000,00, quanto eu terei depois de 10 anos?

valor = 900
for(i in 1:120){
  valor = valor + valor*0.5/100
}
valor
[1] 1637.457

Problema - Investimento

E se o investimento rendesse 0,6% ao mês, qual o valor guardado depois de 10 anos?

valor = 1000
for(i in 1:120){
  valor = valor + valor*0.6/100
}
valor
[1] 2050.018

Problema - Investimento

Será que podemos fazer uma função que:

  • recebe como argumento de entrada:
    • o valor inicial do investimento,
    • o número de meses do investimento,
    • e a taxa de juros; e
  • retorna o montante acumulado?

Problema - Investimento

investimento = function(valor,n,taxa){
  for(i in 1:n){
    valor = valor + valor*taxa/100
  }
  return(valor)
}
investimento(1000,36,0.5)
[1] 1196.681
investimento(1000,120,0.5)
[1] 1819.397
investimento(900,120,0.5)
[1] 1637.457
investimento(1000,120,0.6)
[1] 2050.018

Problema - Investimento

E se quiséssemos saber quantos meses temos que esperar até conseguirmos juntar R$ 15.000,00 com uma aplicação inicial de R$ 1.000, parcelas mensais de R$ 60 e juros de 0,5% ao mês?

Problema - Investimento

Podemos fazer isso com um novo controle de fluxo: whlie

valor = 1000
r = 0.5
parcelas = 60
n = 1
while(valor < 15000){
  valor = valor + valor*r/100 + parcelas
  n = n + 1
}
n
[1] 148
valor
[1] 15061.66

Problema - Investimento

Outra opção é o repeat.

valor = 1000
r = 0.5
parcelas = 60
n = 1
repeat{
  valor = valor + valor*r/100 + parcelas
  n = n + 1
  if(valor > 15000){
    break
  }
}
n
[1] 148
valor
[1] 15061.66

Problema - Investimento

Que tal uma função?

Problema - Investimento

Que tal uma função?

meses_para_juntar = function(montante,investimento,parcelas,r){
  n = 1
  valor = investimento
  repeat{
    valor = valor + valor*r/100 + parcelas
    n = n + 1
    if(valor > montante){
      break
    }
  }
  return(c(n,valor))
}

Problema - Investimento

meses_para_juntar(15000,1000,60,0.5)
[1]   148.00 15061.66
meses_para_juntar(20000,1200,100,0.5)
[1]   129.00 20141.33
meses_para_juntar(15000,1000,60,0.5)
[1]   148.00 15061.66

Crescimento Populacional

Queremos simular o crescimento de uma população de microorganismos dentro de um laboratório.

  • Chamamos de taxa de nascimento semanal o quanto a população cresce, em porcentagem, a cada semana.
  • Chamamos de taxa de mortalidade semanal o quanto a população diminui, em porcentagem, a cada semana.

Problema - Crescimento Populacional

Suponha uma população inicial de 100 microorganismos com taxa de nascimento de 20% e taxa de morte de 5%. Depois de 4 semanas, qual o tamanho da população?

pop = 1000
for(i in 1:4){
  pop = pop + 0.2*pop - 0.05*pop
}
pop
[1] 1749.006

Problema - Crescimento Populacional

Depois de 8 semanas, qual o tamanho da população?

pop = 1000
for(i in 1:8){
  pop = pop + 0.2*pop - 0.05*pop
}
pop
[1] 3059.023

Problema - Crescimento Populacional

Vamos fazer uma função que

  • recebe como antrada:
    • o tamanho inicial da população;
    • a taxa de nascimento
    • a taxa de morte
    • o tempo de espera
  • e retorna o tamanho da população ao final da simulação.

Problema - Crescimento Populacional

populacao = function(pop,nas,mor,n){
  for(i in 1:n){
    pop = pop + nas*pop - mor*pop
  }
  return(pop)
}

Problema - Crescimento Populacional

Assim fica fácil de comparar diferentes situações.

populacao(1000,0.2,0.05,20)
[1] 16366.54
populacao(1000,0.2,0.2,20)
[1] 1000
populacao(1000,0.05,0.2,20)
[1] 38.75953

Problema - Crescimento Populacional

Suponha agora condições limitadas de alimentação.

  • A mesma taxa de nascimento de 20%.
  • A taxa de mortalidade que será diferente.
    • Para população menor que 2.000, a taxa de mortalidade é de 5%.
    • Para poulação acima de 2.000, a taxa de mortalidade é 5% + (tamanho da populacao - 2000)/10000

Problema - Crescimento Populacional

Qual o tamanho dessa populacao depois de 20 dias?

for(i in 1:20){
  if(pop < 2000){
    pop = pop + 0.2*pop - 0.05*pop
  } else {
    pop = pop + 0.2*pop - (0.05 + (pop-2000)/10000)*pop
  }
}
pop
[1] 3499.902

Problema - Crescimento Populacional

Vamos fazer uma nova função para esse novo cenário.

populacao2 = function(pop,nas,mor,n){
  for(i in 1:n){
    if(pop < 2000){
      pop = pop + nas*pop - mor*pop
    } else {
      pop = pop + 0.2*pop - (0.05 + (pop-2000)/10000)*pop
    }
  }
  return(pop)
}

Problema - Crescimento Populacional

populacao(1000,0.2,0.05,20)
[1] 16366.54
populacao2(1000,0.2,0.05,20)
[1] 3494.66
populacao(1000,0.2,0.2,20)
[1] 1000
populacao2(1000,0.2,0.2,20)
[1] 1000
populacao(1000,0.05,0.2,20)
[1] 38.75953
populacao2(1000,0.05,0.2,20)
[1] 38.75953

Problema - Crescimento Populacional

Seria interessante a gente observar o crescimento dessa populacao ao longo das semanas.

Primeiro para o cenário em que não há restrição de alimentos.

populacao_vec = function(pop,nas,mor,n){
  vec_pop = pop
  for(i in 1:n){
    pop = pop + nas*pop - mor*pop
    vec_pop = c(vec_pop,pop)
  }
  return(vec_pop)
}

Problema - Crescimento Populacional

populacao_vec(1000,0.2,0.05,100)
  [1] 1.000000e+03 1.150000e+03 1.322500e+03 1.520875e+03 1.749006e+03
  [6] 2.011357e+03 2.313061e+03 2.660020e+03 3.059023e+03 3.517876e+03
 [11] 4.045558e+03 4.652391e+03 5.350250e+03 6.152788e+03 7.075706e+03
 [16] 8.137062e+03 9.357621e+03 1.076126e+04 1.237545e+04 1.423177e+04
 [21] 1.636654e+04 1.882152e+04 2.164475e+04 2.489146e+04 2.862518e+04
 [26] 3.291895e+04 3.785680e+04 4.353531e+04 5.006561e+04 5.757545e+04
 [31] 6.621177e+04 7.614354e+04 8.756507e+04 1.006998e+05 1.158048e+05
 [36] 1.331755e+05 1.531519e+05 1.761246e+05 2.025433e+05 2.329248e+05
 [41] 2.678635e+05 3.080431e+05 3.542495e+05 4.073870e+05 4.684950e+05
 [46] 5.387693e+05 6.195847e+05 7.125224e+05 8.194007e+05 9.423108e+05
 [51] 1.083657e+06 1.246206e+06 1.433137e+06 1.648108e+06 1.895324e+06
 [56] 2.179622e+06 2.506566e+06 2.882550e+06 3.314933e+06 3.812173e+06
 [61] 4.383999e+06 5.041599e+06 5.797838e+06 6.667514e+06 7.667641e+06
 [66] 8.817787e+06 1.014046e+07 1.166152e+07 1.341075e+07 1.542237e+07
 [71] 1.773572e+07 2.039608e+07 2.345549e+07 2.697381e+07 3.101989e+07
 [76] 3.567287e+07 4.102380e+07 4.717737e+07 5.425397e+07 6.239207e+07
 [81] 7.175088e+07 8.251351e+07 9.489054e+07 1.091241e+08 1.254927e+08
 [86] 1.443166e+08 1.659641e+08 1.908588e+08 2.194876e+08 2.524107e+08
 [91] 2.902723e+08 3.338132e+08 3.838852e+08 4.414679e+08 5.076881e+08
 [96] 5.838413e+08 6.714175e+08 7.721302e+08 8.879497e+08 1.021142e+09
[101] 1.174313e+09

Problema - Crescimento Populacional

v1 = populacao_vec(1000,0.2,0.05,100)
plot(v1)

Problema - Crescimento Populacional

Agora considerando a restrição de alimentos.

populacao2_vec = function(pop,nas,mor,n){
  vec_pop = pop
  for(i in 1:n){
    if(pop < 2000){
      pop = pop + nas*pop - mor*pop
    } else {
      pop = pop + 0.2*pop - (0.05 + (pop-2000)/10000)*pop
    }
    vec_pop = c(vec_pop,pop)
  }
  return(vec_pop)
}

Problema - Crescimento Populacional

populacao2_vec(1000,0.2,0.05,100)
  [1] 1000.000 1150.000 1322.500 1520.875 1749.006 2011.357 2310.776 2585.579
  [9] 2822.010 3013.340 3159.987 3267.431 3343.421 3395.772 3431.165 3454.784
 [17] 3470.405 3480.676 3487.402 3491.795 3494.660 3496.526 3497.741 3498.531
 [25] 3499.045 3499.379 3499.596 3499.738 3499.829 3499.889 3499.928 3499.953
 [33] 3499.970 3499.980 3499.987 3499.992 3499.995 3499.996 3499.998 3499.999
 [41] 3499.999 3499.999 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [49] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [57] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [65] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [73] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [81] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [89] 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000 3500.000
 [97] 3500.000 3500.000 3500.000 3500.000 3500.000

Problema - Crescimento Populacional

v2 = populacao2_vec(1000,0.2,0.05,100)
plot(v2)

Problema - Crescimento Populacional

Figure 1: Alimentos ilimitados

Figure 2: Alimentos limitados

Fatoração

Como a gente faz para fatorar um número?

Qual seria a fatoração do número 1234567890 em fatores primos?

Problema - Fatoração

  • Passo 1: O primeiro divisor é \(d = 2\).
  • Passo 2: Se o número for divisível por \(d\), divide ele por \(d\) e verifica o quociente:
    • Se o quiciente for 1, fim.
    • Se o quiciente for diferente de 1, repete o passo 2, agora com o quociente.
  • Passo 3: Se o número não for divisível por \(d\), segue.
  • Passo 4: Faça \(d = d + 1\) e volte para o passo 2.

Problema - Fatoração

options(digits=10)
1234567890/2
[1] 617283945
quociente = 1234567890/2
quociente
[1] 617283945
## fatores: 2
quociente/2
[1] 308641972.5
quociente/3
[1] 205761315
quociente = quociente/3
quociente
[1] 205761315
## fatores: 2, 3
quociente/3
[1] 68587105
quociente = quociente/3
quociente
[1] 68587105
## fatores: 2, 3, 3
quociente/3
[1] 22862368.33
quociente = quociente/3
quociente
[1] 22862368.33
## fatores: 2, 3, 3, 3
quociente/3
[1] 7620789.444
quociente/4
[1] 5715592.083
quociente/5
[1] 4572473.667
quociente = quociente/5
quociente
[1] 4572473.667
## fatores: 2, 3, 3, 3, 5
quociente/5
[1] 914494.7333
quociente/6
[1] 762078.9444
quociente/7
[1] 653210.5238
quociente/8
[1] 571559.2083
quociente/11
[1] 415679.4242
quociente/13
[1] 351728.7436
quociente/17
[1] 268969.0392
quociente/23
[1] 198803.2029
quociente/29
[1] 157671.5057
quociente/31
[1] 147499.1505
quociente/37
[1] 123580.3694
quociente/41
[1] 111523.748
quociente/43
[1] 106336.5969
## muito trabalhoso.. vamos fazer um programa que faca isso pra gente?

Problema - Fatoração

quociente = 1234567890
fatores = NULL
d = 2
while(quociente>1){
  if(quociente%%d==0){
    quociente = quociente/d
    fatores = c(fatores,d)
  } else {
    d = d + 1
  }
}
fatores
[1]    2    3    3    5 3607 3803

Problema - Fatoração

Vamos fazer uma função que recebe um número qualquer e retorna um vetor com a fatoração deste número em fatores primos?

fatoracao  = function(numero){
  quociente = numero
  fatores = NULL
  d = 2
  while(quociente>1){
    if(quociente%%d==0){
      quociente = quociente/d
      fatores = c(fatores,d)
    } else {
      d = d + 1
    }
  }
  return(fatores)
}

Problema - Fatoração

fatoracao(123456)
[1]   2   2   2   2   2   2   3 643
fatoracao(5542132)
[1]     2     2    29 47777

Problema - Fatoração

Será que a função fatoracao consegue ajudar a gente a definir outra função capaz de identificar se um número é primo ou não?

Problema - Fatoração

  • Criamos uma função muito parecida com a fatoracao, só que ela será interrompida se encontrarmos um fator, pois já sabemos que o número não será primeiro.

  • Se a função chegar ao “final”, o único fator do número será o próprio número logo ele será um número primo.

Problema - Fatoração

eh_primo  = function(numero){
  if(numero == 1 || numero == 2){
    return(TRUE)
  }
  d = 2
  while(d<numero){
    if(numero%%d==0){
      return(FALSE)
    } else {
      d = d + 1
    }
  }
  return(TRUE)
}

Problema - Fatoração

eh_primo(12345678989)
[1] FALSE
eh_primo(13)
[1] TRUE
eh_primo(59)
[1] TRUE
eh_primo(8317)
[1] TRUE

Problema - Fatoração

E se quiséssemos uma função que retornasse todos os primos menores que um número dado como argumento de entrada?

Problema - Fatoração

E se quiséssemos uma função que retornasse todos os primos menores que um número dado como argumento de entrada?

primos_menores_que = function(N){
  primos = NULL
  for(i in 1:N){
    if(eh_primo(i)){
      primos = c(primos,i)
    }
  }
  return(primos)
}

Problema - Fatoração

primos_menores_que(1000)
  [1]   1   2   3   5   7  11  13  17  19  23  29  31  37  41  43  47  53  59
 [19]  61  67  71  73  79  83  89  97 101 103 107 109 113 127 131 137 139 149
 [37] 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241
 [55] 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353
 [73] 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461
 [91] 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587
[109] 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
[127] 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823
[145] 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947
[163] 953 967 971 977 983 991 997

Problema - Fatoração

primos_menores_que(2000)
  [1]    1    2    3    5    7   11   13   17   19   23   29   31   37   41   43
 [16]   47   53   59   61   67   71   73   79   83   89   97  101  103  107  109
 [31]  113  127  131  137  139  149  151  157  163  167  173  179  181  191  193
 [46]  197  199  211  223  227  229  233  239  241  251  257  263  269  271  277
 [61]  281  283  293  307  311  313  317  331  337  347  349  353  359  367  373
 [76]  379  383  389  397  401  409  419  421  431  433  439  443  449  457  461
 [91]  463  467  479  487  491  499  503  509  521  523  541  547  557  563  569
[106]  571  577  587  593  599  601  607  613  617  619  631  641  643  647  653
[121]  659  661  673  677  683  691  701  709  719  727  733  739  743  751  757
[136]  761  769  773  787  797  809  811  821  823  827  829  839  853  857  859
[151]  863  877  881  883  887  907  911  919  929  937  941  947  953  967  971
[166]  977  983  991  997 1009 1013 1019 1021 1031 1033 1039 1049 1051 1061 1063
[181] 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151 1153 1163 1171 1181
[196] 1187 1193 1201 1213 1217 1223 1229 1231 1237 1249 1259 1277 1279 1283 1289
[211] 1291 1297 1301 1303 1307 1319 1321 1327 1361 1367 1373 1381 1399 1409 1423
[226] 1427 1429 1433 1439 1447 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499
[241] 1511 1523 1531 1543 1549 1553 1559 1567 1571 1579 1583 1597 1601 1607 1609
[256] 1613 1619 1621 1627 1637 1657 1663 1667 1669 1693 1697 1699 1709 1721 1723
[271] 1733 1741 1747 1753 1759 1777 1783 1787 1789 1801 1811 1823 1831 1847 1861
[286] 1867 1871 1873 1877 1879 1889 1901 1907 1913 1931 1933 1949 1951 1973 1979
[301] 1987 1993 1997 1999

Obrigada