Apelarea funcțiilor C++ din R folosind Rcpp

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

(Acest articol a fost publicat pentru prima dată pe Laboratorul de software al lui Adamși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)


Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.

Introducere

Dacă sunteți utilizator R/RStudio și învățați C/C++, atunci această postare de blog poate fi interesantă. Să presupunem că ați scris o funcție în C/C++ (sau chiar un program întreg). Știi cum să rulezi codul din linia de comandă, pasând argumente și așa mai departe. Cu toate acestea, acest lucru nu este neapărat foarte convenabil. Nu ar fi frumos să aveți funcționalitatea dvs. C/C++ disponibilă în R? Ei bine, poți. În câțiva pași simpli (folosind Rcpp) puteți face funcțiile dvs. C/C++ disponibile în R/RStudio.

Această postare de blog descrie pașii necesari. Nu mă voi opri prea mult asupra aspectelor tehnice. Detaliile sunt acoperite în altă parte: Rcpp. Ceea ce mă interesează aici este configurarea unui pachet Rcpp care poate apela funcții C++ din R/RStudio.

Vom începe prin a crea un pachet Rcpp. Acest lucru ne va oferi un cadru pe care îl putem folosi pică înăuntru codul C++. Apoi, vom modifica codul Rcpp pentru a apela funcțiile noastre C++ și vom construi pachetul. Pentru referință, folosim următoarele versiuni:

  • Versiunea R 4.4.1
  • RStudio versiunea 2024.04.2 (build 764)
  • RTools versiunea 4.4

1. Crearea unui pachet Rcpp

Urmați acești pași pentru a crea un pachet Rcpp.

În primul rând, asigurați-vă că Rcpp este instalat. Dacă nu, rulați următoarea comandă în RStudio: install.packages("Rcpp")

  • Selectați Fișier > Proiect nou…
  • În dialogul Expert Proiect nou, selectați Director nou
  • În pagina Tip de proiect, derulați în jos lista de tipuri de proiecte și selectați „R Package using Rcpp”.

Pachetul R folosind Rcpp

  • În pagina „Creați pachet R folosind Rcpp”, completați numele directorului. În acest caz este Funcții financiare.
  • Apăsați butonul Creare proiect. Este începută o nouă sesiune RStudio, iar proiectul se deschide cu un util Citește-mă și șterge-mă fişier.

Navigați la directorul src și deschideți fișierul rcpp_hello_world.cpp. Aici există o funcție de test C++ numită rcpp_hello_world() pe care îl putem apela de la R după ce construim pachetul.

Rcpp Bună lumeRcpp Bună lume

  • Selectați meniul: Build > Build binary package

Dacă totul merge bine, ar trebui să vedem un mesaj similar cu acesta:

...
packaged installation of 'FinancialFunctions' as FinancialFunctions_1.0.zip
─  DONE (FinancialFunctions)
(1) "D:/TEMP/FinancialFunctions_1.0.zip"

Binary package written to D:/TEMP

Acum am construit un pachet Rcpp complet funcțional. Deschideți fișierul zip și copiați conținutul în directorul bibliotecii dvs. R (de ex. D:RR-4.4.1library). Apoi, în RStudio, rulați următorul script:

> library(FinancialFunctions)		# Load the package
> results <- rcpp_hello_world()		# Call the C++ function
> results							# Print the results
((1))
(1) "foo" "bar"

((2))
(1) 0 1

2. Adăugarea codului C++

Acum că avem un schelet de lucru, putem adăuga propriile noastre funcții C++ la pachet.

Copiați cele două fișiere FinancialFunctions.h şi FinancialFunctions.cpp în src director.

Există două funcții declarate în fișierul antet: price şi ytm (randament până la maturitate).

Funcția preț calculează valoarea actuală a unui flux de fluxuri de numerar periodice folosind o singură rată de actualizare. Funcția de randament până la scadență calculează rata unică de rentabilitate implicată de fluxurile de numerar periodice și prețul (valoarea actuală).

Funcția preț ia un vector de timpi și un vector de fluxuri de numerar (pentru o obligațiune acestea sunt cupoanele și rambursarea finală a principalului). În plus, funcția ia o singură rată, care este utilizată pentru a reduce toate fluxurile de numerar.

Funcția de randament până la scadență ia, de asemenea, un vector de timpi și un vector de fluxuri de numerar (ca mai sus) și un preț (obligațiuni). Din aceasta, determină iterativ rata unică la care fluxul periodic de numerar ar trebui actualizat pentru a obține prețul furnizat.

3. Conectarea R cu C++ folosind Rcpp

Ștergeți fișierul rcpp_hello_world.cpp deoarece nu mai avem nevoie de funcția de testare. Apoi copiați fișierul rcpp_functions.cpp în src director. Acest fișier conține funcțiile pe care le dorim export de la C++ la R folosind Rcpp.

În partea de sus a fișierului, includem fișierul antet Rcpp principal. Acesta este urmat de vectorul STL include și, în sfârșit, includem declarațiile funcțiilor noastre în FinancialFunctions.h.

Codul din rcpp_functions.cpp declară o funcție Rcpp numită bond_price. Cel mai important, este precedat de linie // ((Rcpp::export)). Acest atribut indică faptul că funcția ar trebui să fie exportateadică făcut vizibil pentru R. La fel de simplu. Rcpp are grijă de toate detaliile. Tot ce ne preocupă este ce parametri ni se trec și cum să ne apelăm funcția și să obținem rezultatele.

The bond_price funcția ia ca parametri doi vectori numerici (timpii și fluxurile de numerar) și o rată (un dublu). Acestea sunt transmise de la R. Funcția returnează o valoare dublă, prețul calculat. Funcția Rcpp arată astfel.

// ((Rcpp::export))
double bond_price(Rcpp::NumericVector times, Rcpp::NumericVector cashflows, double rate)
{
  std::vector _times = Rcpp::as<:vector>>(times);
  std::vector _cashflows = Rcpp::as<:vector>>(cashflows);
  
  double price = FinancialFunctions::Bonds::price(_times, _cashflows, rate);
 
  return price;
}

În interiorul funcției, tipurile Rcpp NumericVector sunt convertite în std::vectorcare este ceea ce se așteaptă funcția noastră.

În cele din urmă apelăm funcția noastră și returnăm rezultatul.

Codul Rcpp pentru bond_ytm este foarte asemănător.

Totul este acum gata pentru a fi construit.

  • Selectați meniul: Build > Build binary package.

Țineți degetele încrucișate că nu am făcut nicio greșeală. Dacă totul merge bine, ar trebui să vedem un mesaj similar cu acesta:

Binary package written to D:/Development/Projects/R

Copiați conținutul fișierului zip în directorul bibliotecii R ca anterior, suprascriind versiunea inițială a pachetului.

Pentru a verifica dacă totul funcționează conform așteptărilor, rulați următorul script.

library(FinancialFunctions)
# Example: a 3 year bond with a face value of $100 makes annual coupon 
# payments of 10%. The current interest rate (with annual compounding) is 9%.
times <- c(1, 2, 3)
cashflows <- c(10, 10, 110)
rate <- 0.09

# Calculate price and yield to maturity
price <- FinancialFunctions::bond_price(times, cashflows, rate)
ytm <- FinancialFunctions::bond_ytm(times, cashflows, price)

# Display the results
price
ytm

Nu ar trebui să existe erori. Putem verifica rezultatele în comparație cu calculele manuale într-o foaie de calcul, dacă este necesar.

Învelire.

Asta e tot ce este. Acum avem un pachet Rcpp de lucru care apelează funcții C/C++ din R.

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.