SAUDAÇÕES!

Seja bem vindo à página do professor Pedro Albuquerque. Para saber mais sobre meu currículo, disciplinas ministradas e interesses de pesquisa, navegue no menu disponível no topo da página.

quarta-feira, 15 de fevereiro de 2017

Introdução ao RCpp - Parte 2.


Dando continuidade ao post de Introdução ao RCpp - Parte 1. Aqui eu mostrarei como os objetos do Rcpp se relacionam com os objetos em R. Os principais objetos do Rcpp são:

  1. NumericVector - Objeto representando um vetor numérico no R.
  2. CharacterVector - Objeto representando um vetor caracter no R.
  3. NumericMatrix - Objeto representando uma matriz numérica no R.
  4. CharacterMatrix - Objeto representando uma matriz caracter no R.
  5. LogicalVector - Objeto representando um vetor lógico no R.
  6. IntegerVector - Objeto representando um vetor inteiro no R.
  7. LogicalMatrix - Objeto representando uma matriz lógica no R.
  8. IntegerMatrix - Objeto representando uma matriz inteira no R.
  9. List - Objeto representando uma lista no R.

Aqui trabalharemos com exemplos de vetores e nos próximos posts o uso de matrizes e listas. Suponha que temos um vetor de retornos e um vetor com os nomes dos ativos representando esses vetores, algo como:

#Invoca a biblioteca RCpp
library(Rcpp)
#Define o endereço do arquivo Cpp
setwd("C:\\Blog\\Source")
#Define a semente para simulação dos dados
set.seed(19393)
#Gera um vetor numérico de retornos:
ret<-rnorm(1000, 0,0.1)
#Gera um vetor caracter de nomes:
nomes<-replicate(1000, paste(sample(LETTERS, 5, replace=TRUE), collapse=""))
Com base nesses dois inputs podemos pensar em algumas funções escritas em Rcpp que utilizem esses insumos. Por exemplo, considere que desejamos obter os 5 menores valores do vetor ret e os respectivos nomes dessas empresas.
//Exemplo de função para obter os k menores valores.
// [[Rcpp::export]]
NumericVector kMenores(int k, NumericVector ret, CharacterVector nomes) {
  //Cria um vetor numérico de tamanho k
  NumericVector vetMenoresRetornos(k);
  //Cria um vetor caracter de tamanho k
  CharacterVector vetMenoresNomes(k);
  //Faz o loop para achar os k menores
  for (int i = 0; i < ret.size(); i++){
    //Verifica qual menor é:
    int iMenor = qualMenor(ret[i],vetMenoresRetornos);
    if(iMenor>-1){
      vetMenoresRetornos[iMenor]=ret[i];
    }
    
  }
  return vetMenoresRetornos;
}
Onde a função qualMenor é criada no topo do mesmo arquivo em C++ da seguinte forma:
#include 
using namespace Rcpp;

//Função para dizer qual posição esse menor é:
int qualMenor(double valor,NumericVector vetMenoresRetornos){
  //Inicializa a variável
  int menor=-1;
  //Procura qual o menor:
  for(int i=0;i< vetMenoresRetornos.size();i++){
    if(valor<=vetMenoresRetornos[i])  return i;
  }
  return(menor);
}
Observe que as linhas 1 e 2 do código anterior são mandatórias e devem constar em todos os arquivo com extensão .cpp, ademais como o código anterior não contêm a linha // [[Rcpp::export]] isso significa que a função é interna e não pode ser invocada pelo R. Finalmente, a invocação no R é feito da seguinte forma:
#Invoca a biblioteca RCpp
library(Rcpp)
#Define o endereço do arquivo Cpp
setwd("C:\\Blog\\Source")
#Compila o código em C++
sourceCpp('Teste.cpp')
#Inova a função compilada
teste<-kMenores(5,ret,nomes)
#Confere com a função do R
head(sort(teste),5)
Repare que em nenhum momento utilizamos o objeto nomes. Para imprimir o nome das empresas com menor retorno no console podemos alterar a função kMenores da seguinte forma:
//Exemplo de função para obter os k menores valores.
// [[Rcpp::export]]
NumericVector kMenores(int k, NumericVector ret, CharacterVector nomes) {
  //Cria um vetor numérico de tamanho k
  NumericVector vetMenoresRetornos(k);
  //Cria um vetor caracter de tamanho k
  CharacterVector vetMenoresNomes(k);
  //Faz o loop para achar os k menores
  for (int i = 0; i < ret.size(); i++){
    //Verifica qual menor é:
    int iMenor = qualMenor(ret[i],vetMenoresRetornos);
    if(iMenor>-1){
      //Guarda os retornos mínimos
      vetMenoresRetornos[iMenor]=ret[i];
      //Guarda os nomes das firmas
      vetMenoresNomes[iMenor]=nomes[i];
    }
  }
  //Antes de retornar os resultados imprimir no console o nome
  for(int j=0;j < k;j++){
    std::cout << "Firma: " << vetMenoresNomes[j] << " Retorno: " << vetMenoresRetornos[j] << std::endl;
  }
  return vetMenoresRetornos;
}
A invocação procede de maneira equivalente a apresentada anteriormente, a diferença é que agora no console do R o nome das firmas e seus retornos simulados são apresentados. Alguns links interessantes para mais detalhes sobre o RCpp:
  1. http://adv-r.had.co.nz/Rcpp.html
  2. http://gallery.rcpp.org/articles/r-function-from-c++/
  3. http://pages.stat.wisc.edu/~gvludwig/Rcpp/