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.
Mostrando postagens com marcador RStudio. Mostrar todas as postagens
Mostrando postagens com marcador RStudio. Mostrar todas as postagens

sábado, 15 de abril de 2017

Introdução ao RCpp - Parte 4.


Frequentemente é necessário inicializar um NumericVector com algum valor de constante fixo, nesse caso podemos usar a função fill(.):

#include 
using namespace Rcpp;
// Função para repetir o valor no vetor
// [[Rcpp::export]]
NumericVector inicializaVetor(double valor, int tamanho) {
  NumericVector x(tamanho);
  x.fill(valor);
  return x;
}

Após compilar o código, a invocação no R é quase imediata:

#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')
inicializaVetor(2,5)

O pacote Rcpp tem muitas funcionalidades. Por meio do Rcpp podemos por exemplo, usar funções já implementadas no R, como:

// [[Rcpp::export]]
NumericVector calculaCurtose(NumericVector x) {
  Rcpp::Environment funcoesPacote("package:e1071");
  Rcpp::Function funcaoCurtose = funcoesPacote["kurtosis"];
  return funcaoCurtose (x);
}

Ou por exemplo, gerar números com a distribuição normal:

// [[Rcpp::export]]
NumericVector geraNormal(){
  Rcpp::Environment stats("package:stats");
  Rcpp::Function rnorm = stats["rnorm"];
  return rnorm(10, Rcpp::Named("sd", 100.0));
}

Comandos esses que após compilados são invocados na 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')
#Executa as funções:
x<-rnorm(1919)
calculaCurtose(x)
geraNormal()
Entre os objetos mais flexíveis do Rcpp está o objeto GenericVector o qual funciona como uma lista permitindo a inserção de qualquer outro objeto em seus slots. Além do mais, é possível usar os seguintes métodos nesse objeto:
  • push_back(x) - Insere o elemento x no final da lista.
  • push_front(x) - Insere o elemento x no início da lista.
  • insert(i, x) - Insere o elemento x na posição i.
  • erase(i) - Apaga o elemento existente na posição i.

Todas essas funções são dinâmicas e não há a necessidade de criar uma nova lista para que os novos elementos sejam inseridos.

quarta-feira, 15 de março de 2017

Introdução ao RCpp - Parte 3.


Aqui neste post continuaremos com a análise dos possíveis métodos desenvovidos usando Rcpp. O primeiro exemplo trata do uso de matrizes, especificamente, vamos criar uma função para fazer a transposição de uma matriz:

#include 
using namespace Rcpp;
// Função para transposição de matriz
// [[Rcpp::export]]
NumericMatrix transpose(NumericMatrix x) {
  //Obtêm o número de linhas e colunas:
  int nrow = x.nrow(), ncol = x.ncol();
  //Cria a matriz com resultado
  NumericMatrix resultado(ncol,nrow);
  //Faz a transposição:
  for(int i=0;i < nrow; i++){
    for(int j=0;j < ncol; j++){
      resultado(j,i)=x(i,j);
    }
  }
  return resultado;
}
Após compilar o código, a invocação no R é quase imediata:
#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')
#Cria uma matriz de exemplo
mat<-matrix(c(2,8,9,0,0,0,4,3,2), nrow=3,ncol=3)
#Transpoem a matriz
transpose(mat)
Métodos mais sofisticados usando funções implementadas em R e invocadas em C++ também podem ser utilizadas:
//Usando funções do R:
// [[Rcpp::export]]
NumericVector ExemploKernel(NumericVector x, NumericVector y, Function f) {
  NumericVector res = f(x,y);
  return res;
}
Método esse que recebe como argumento dois vetores numéricos e uma função bivariada:
#Cria uma função no R
gaussian<-function(x,y){
  return(sum((x-y)^2))
}
#Gera dois vetores
x<-rnorm(1000)
y<-rnorm(1000)
#Invoca a função em Rcpp:
ExemploKernel(x,y,gaussian)



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/





segunda-feira, 16 de janeiro de 2017

Introdução ao RCpp - Parte 1.


O R possui uma limitação devido a demora de alguns procedimentos realizados nele. O software foi criado para ser ótimo do ponto de vista de processamento computacional quando o usuário utiliza as informações de maneira vetorizada. Quando o processo é realizado de elemento a elemento alguma demora no processamento surge.

Nesse sentido, aqui daremos uma primeira introdução quanto ao uso do pacote RCpp (http://www.rcpp.org/), o qual permite otimizar alguns procedimentos em R usando linguagem C++.

O primeiro passo para desenvolver suas próprias funções em RCpp é ter instalado:

  1. R
  2. RTools - É preciso que ele esteja instalado na raiz (C:\) e com todas as opções habilitadas.
  3. RStudio

Em seguida, abrimos o RStudio e escolhemos a opção File → New File → C++ File:


O RStudio fornecerá um exemplo de como construir funções usando RCpp:


Onde o primeiro bloco de código, da linha 1 até a 24 é código escrito em C++, o que está contido na linha 26 é o código em R usando para a invocação da função em C++. Para compilar a função é necessário clicar no botão Source destacado na figura anterior. Ao clicar nesse botão a função é compilada e fica disponível para ser executada.

É comum no entanto ter dois arquivos: um arquivo com as funções em C++ e outro arquivo com as funções em R, por isso considere o seguinte código para o arquivo com extensão .cpp:

#include 
using namespace Rcpp;
// This is a simple example of exporting a C++ function to R. 
// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
  return x * 2;
}

E no arquivo em R (com extensão .R):

#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
timesTwo(42)

Note que nesse exemplo, Teste.cpp é o nome do arquivo com o código em RCpp armazenado na pasta C:\Blog\Source. No próximo post mostrarei como fazer funções mais complexas envolvendo os pacotes do R e seus objetos com o Rcpp.