{"id":14067205,"url":"https://github.com/stefan-m-lenz/JuliaConnectoR","last_synced_at":"2025-07-30T00:32:55.173Z","repository":{"id":40649731,"uuid":"180594311","full_name":"stefan-m-lenz/JuliaConnectoR","owner":"stefan-m-lenz","description":"A functionally oriented interface for calling Julia from R","archived":false,"fork":false,"pushed_at":"2024-10-09T08:41:20.000Z","size":717,"stargazers_count":103,"open_issues_count":3,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-12-04T07:36:51.006Z","etag":null,"topics":["interoperability","julia","r","r-package"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stefan-m-lenz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-10T14:02:39.000Z","updated_at":"2024-11-03T04:18:07.000Z","dependencies_parsed_at":"2022-07-14T08:18:10.737Z","dependency_job_id":"343f715c-5a0e-49fc-8703-0533f78e03a6","html_url":"https://github.com/stefan-m-lenz/JuliaConnectoR","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/stefan-m-lenz/JuliaConnectoR","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefan-m-lenz%2FJuliaConnectoR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefan-m-lenz%2FJuliaConnectoR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefan-m-lenz%2FJuliaConnectoR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefan-m-lenz%2FJuliaConnectoR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stefan-m-lenz","download_url":"https://codeload.github.com/stefan-m-lenz/JuliaConnectoR/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefan-m-lenz%2FJuliaConnectoR/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267785798,"owners_count":24144122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interoperability","julia","r","r-package"],"created_at":"2024-08-13T07:05:28.863Z","updated_at":"2025-07-30T00:32:54.856Z","avatar_url":"https://github.com/stefan-m-lenz.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"# JuliaConnectoR \u003cimg src=\"JuliaConnectoR-Logo.svg\" align=\"right\" width=\"120\" /\u003e\n\n[![CRAN version](https://www.r-pkg.org/badges/version/JuliaConnectoR)](https://CRAN.R-project.org/package=JuliaConnectoR)\n[![Build Status](https://github.com/stefan-m-lenz/JuliaConnectoR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/stefan-m-lenz/JuliaConnectoR/actions)\n[![codecov](https://codecov.io/gh/stefan-m-lenz/JuliaConnectoR/branch/master/graph/badge.svg?token=sCnEUyStzW)](https://codecov.io/gh/stefan-m-lenz/JuliaConnectoR)\n\nThis R-package provides a functionally oriented interface between R and Julia.\nThe goal is to call functions from Julia packages directly as R functions.\nJulia functions imported via the `JuliaConnectoR` can accept and return R variables.\nIt is also possible to pass R functions as arguments in place of Julia functions, which allows callbacks from Julia to R.\n\nFrom a technical perspective, R data structures are serialized with an optimized custom streaming format,\nsent to a (local) Julia TCP server, and translated to Julia data structures by Julia.\nThe results of function calls are likewise translated back to R.\nComplex Julia structures can either be used by\nreference via proxy objects in R or fully translated to R data structures.\n\nMore details about the package together with a comparison with competing solutions can be found in the article:\n\n\u003e Lenz, S., Hackenberg, M., \u0026 Binder, H. (2022). The JuliaConnectoR: a functionally oriented interface for integrating Julia in R. *Journal of Statistical Software*, 101(6), 1–24. https://doi.org/10.18637/jss.v101.i06\n\n\n## Installation\n\nThe package can be installed in R (version \u0026ge; 3.2) via CRAN:\n\n    install.packages(\"JuliaConnectoR\")\n\nOr the development version can be installed with:\n\n    devtools::install_github(\"stefan-m-lenz/JuliaConnectoR\")\n\nThe package requires that [Julia (version \u0026ge; 1.0) is installed](https://julialang.org/downloads/).\nIf Julia is installed with Juliaup, it should be discovered successfully.\nOtherwise, make sure your Julia installation is on the system `PATH` or set the `JULIA_BINDIR` system variable.\nMore information on that can be found in the [latest documentation](https://github.com/stefan-m-lenz/JuliaConnectoR/releases/download/v1.1.4/JuliaConnectoR.pdf).\n\n\n## Overview\n\nThe following table lists the most important functions exported by the package:\n\n| Function name | Description |\n|---------------|-------------|\n| `juliaImport` | Load a Julia package in Julia via `import` and return its functions and data types as an environment, such that the functions can be called directly in R |\n| `juliaFun` | Create an R function that wraps a Julia function |\n| `juliaCall` | Call any Julia function by name. Not needed for functions attached via `juliaImport` or created via `juliaFun`. |\n| `juliaEval` | Evaluate a simple Julia expression (and return the result) |\n| `juliaLet` | Evaluate Julia expressions with R variables in place of Julia variables employing a `let` block (and return the result) |\n| `juliaGet` | Fully translate a Julia object to an R object |\n| `juliaExpr` | Use a Julia expressions or refer to a Julia object via a string in R |\n\nFor a detailed description of the functions with some examples, and for more details about the translation of data structures, please see the [latest documentation](https://github.com/stefan-m-lenz/JuliaConnectoR/releases/download/v1.1.4/JuliaConnectoR.pdf).\n\n## Examples\n\n## Using Flux\n\nWith the `JuliaConnectoR` it is possible to use, e. g., the [Flux](https://github.com/FluxML/Flux.jl) Julia package for training a neural network on the famous `iris` data set.\n\nYou can see that the translation from Julia to R code is rather straightforward:\n\nBelow we see example code for training a neural network for classification on the famous `iris` data set in Julia and its translation in R. Both the Julia version of the script and the R version are two complete runnable examples, showing all important steps in training a neural network.\n\n\u003c!-- Julia-iris-data --\u003e\n\u003cdetails\u003e\u003csummary\u003eJulia script: Data preparation\u003c/summary\u003e\n\n```julia\nusing Pkg\nPkg.add(PackageSpec(name = \"RDatasets\", version = \"0.7\"))\nPkg.add(PackageSpec(name = \"Flux\", version = \"0.14\"))\n\n# Import packages and set a seed\nimport Flux\nusing Random\nRandom.seed!(1);\n\n# Load data and split it into training and test data\nfunction prepare_data(x, labels)\n   nsamples = size(x, 2)\n   x = Matrix{Float32}(x)\n   testidxs = randperm(nsamples)[1:(round(Int, nsamples*0.3))]\n   trainidxs = setdiff(1:nsamples, testidxs)\n   x_train = x[:, trainidxs]\n   x_test = x[:, testidxs]\n   y = Flux.onehotbatch(labels, unique(labels))\n   y_train = y[:, trainidxs]\n   y_test = y[:, testidxs]\n   (training = (x = x_train, y = y_train),\n         test = (x = x_test, y = y_test))\nend\n\nusing RDatasets\nimport Tables\niris = dataset(\"datasets\", \"iris\")\nx = Tables.matrix(iris[:, 1:4])'\ndata = prepare_data(x, iris[:, :Species])\ntrainingdata = data.training\ntestdata = data.test\n```\n\n\u003c/details\u003e\n\n\u003c!-- Julia-iris-training --\u003e\n\u003cdetails\u003e\u003csummary\u003eJulia script: model training and evaluation\u003c/summary\u003e\n\n```julia\n# Load necessary features\nimport Flux\nusing Statistics\n\n# Train the Flux model\nmodel = Flux.Chain(\n      Flux.Dense(4, 4, Flux.relu),\n      Flux.Dense(4, 4, Flux.relu),\n      Flux.Dense(4, 3),\n      Flux.softmax)\n\nloss(model, x, y) = Flux.crossentropy(model(x), y)\nloss(model, data::NamedTuple) = loss(model, data.x, data.y)\n\nfunction train_network!(model, x, y; epochs, callback)\n   opt = Flux.setup(Flux.Adam(), model);\n   for i in 1:epochs\n      Flux.train!(loss, model, [(x, y)], opt)\n      callback(i)\n   end\nend\n\nepochs = 2500\ntrain_losses = Vector{Float32}(undef, epochs);\ntest_losses = Vector{Float32}(undef, epochs);\ntrain_network!(model, trainingdata.x, trainingdata.y, epochs = epochs,\n      callback = (i) -\u003e begin\n         train_losses[i] = loss(model, trainingdata)\n         test_losses[i] = loss(model, testdata)\n      end)\n\n# (Could plot losses here)\n\n# Evaluate model\naccuracy(model, data) =\n      mean(Flux.onecold(model(data.x)) .== Flux.onecold(data.y))\naccuracy(model, trainingdata)\naccuracy(model, testdata)\n```\n\n\u003c/details\u003e\n\n\u003c!-- R-iris-data --\u003e\n\u003cdetails\u003e\u003csummary\u003eAdapted R/JuliaConnectoR script: data preparation\u003c/summary\u003e\n\n```R\nlibrary(JuliaConnectoR)\n\njuliaEval('using Pkg; Pkg.add(PackageSpec(name = \"Flux\", version = \"0.14\"))')\n\n# The Julia code can simply be reused\nprepare_data \u003c- juliaEval('\n      import Flux\n      using Random\n      Random.seed!(1);\n\n      function prepare_data(x, labels)\n         nsamples = size(x, 2)\n         x = Matrix{Float32}(x)\n         testidxs = randperm(nsamples)[1:(round(Int, nsamples*0.3))]\n         trainidxs = setdiff(1:nsamples, testidxs)\n         x_train = x[:, trainidxs]\n         x_test = x[:, testidxs]\n         y = Flux.onehotbatch(labels, unique(labels))\n         y_train = y[:, trainidxs]\n         y_test = y[:, testidxs]\n         (training = (x = x_train, y = y_train),\n               test = (x = x_test, y = y_test))\n      end')\n\nx \u003c- as.matrix(iris[, 1:4])\nlabels \u003c- iris[, \"Species\"]\ndata \u003c- prepare_data(t(x), labels)\ntrainingdata \u003c- data$training\ntestdata \u003c- data$test\n```\n\n\u003c/details\u003e\n\n\u003c!-- R-iris-training --\u003e\n\u003cdetails open\u003e\u003csummary\u003eAdapter R/JuliaConnectoR script: model training and evaluation\u003c/summary\u003e\n\n```R\nlibrary(JuliaConnectoR)\n\n# load Flux features available in R\nFlux \u003c- juliaImport(\"Flux\")\n\njuliaEval(\"using Statistics\") # for Julia code only\n\njuliaEval(\"import Random; Random.seed!(11);\")\nmodel \u003c- Flux$Chain(\n      Flux$Dense(4L, 4L, Flux$relu),\n      Flux$Dense(4L, 4L, Flux$relu),\n      Flux$Dense(4L, 3L),\n      Flux$softmax)\n\nloss \u003c- juliaEval('loss(model, x, y) = Flux.crossentropy(model(x), y)\n                  loss(model, data::NamedTuple) = loss(model, data.x, data.y)')\n\ntrain_network \u003c- juliaEval('\n   function train_network!(model, x, y; epochs, callback)\n      opt = Flux.setup(Flux.Adam(), model);\n      for i in 1:epochs\n         Flux.train!(loss, model, [(x, y)], opt)\n         callback(i)\n      end\n   end')\n\nplotLoss \u003c- function(epoch, loss_train, loss_test, epochs) {\n   if (epoch == 1) {\n      ymax \u003c- max(loss_train, loss_test)\n      plot(x = c(1, 1), y = c(loss_train, loss_test),\n           xlim = c(0, epochs), ylim = c(0, ymax*1.1),\n           col = c(\"red\", \"blue\"), xlab = \"Epoch\", ylab = \"Loss\")\n      legend(\"topright\", legend = c(\"Training data\", \"Test data\"),\n             col = c(\"red\", \"blue\"), pch = 1)\n   } else {\n      points(x = c(epoch, epoch), y = c(loss_train, loss_test),\n             col = c(\"red\", \"blue\"))\n   }\n}\n\nepochs \u003c- 2500\ntrain_losses \u003c- rep(0, epochs)\ntest_losses \u003c- rep(0, epochs)\ntrain_network(model, trainingdata$x, trainingdata$y, epochs = epochs,\n      callback = function(i) {\n         train_losses[i] \u003c\u003c- loss(model, trainingdata)\n         test_losses[i] \u003c\u003c- loss(model, testdata)\n         plotLoss(i, train_losses[i], test_losses[i], epochs)\n      })\n\naccuracy \u003c- juliaEval(\"accuracy(model, data) =\n      mean(Flux.onecold(model(data.x)) .== Flux.onecold(data.y))\")\naccuracy(model, trainingdata)\naccuracy(model, testdata)\n```\n\n\u003c/details\u003e\n\nUsing the callback makes it possible to plot the training curve\nduring the training.\nThis example runs so fast that it is not really possible to watch the\ntraining progress.\nIn our case it would be better to optimize the training function to accumulate the losses in Julia and plot them in the end of the training.\nHowever, the example demonstrates the principle of how callback functions can be used to watch the progress during the training.\n\n### Using *BoltzmannMachines* in R\n\nThe following example code shows how the `JuliaConnectoR` can be used with the Julia package [`BoltzmannMachines`](https://github.com/stefan-m-lenz/BoltzmannMachines.jl) in R.\n\n\n\u003c!-- Boltzmann-Example --\u003e\n```R\nlibrary(JuliaConnectoR)\n\n# Test BoltzmannMachines package\n# If not installed, install the current version via\n# juliaEval('using Pkg; Pkg.add(\"BoltzmannMachines\"))')\n\n# Set a random seed in Julia\njuliaEval(\"using Random; Random.seed!(5);\")\n\nBM \u003c- juliaImport(\"BoltzmannMachines\")\n\n# a test data set from the BoltzmannMachines-package, just to have some data\nx \u003c- BM$barsandstripes(100L, 4L)\nx\n\n# Train DBMs with\ndbm \u003c- BM$fitdbm(x, epochs = 40L, learningrate = 0.05,\n                 nhiddens = c(4L,3L))\ndbm\ndbm2 \u003c- BM$fitdbm(x, epochs = 10L,\n                  pretraining = list(BM$TrainLayer(nhidden = 4L),\n                                     BM$TrainLayer(nhidden = 3L)))\ndbm2\n\n# Use a trained model to generate samples\nBM$samples(dbm, 10L)\n\n# Evaluate the model: Likelihood estimation ...\nBM$loglikelihood(dbm2, x)\n#  ... or exact calculation (possible for such a small model)\nBM$exactloglikelihood(dbm2, x)\n\n# RBM-fitting with simple monitoring, e. g. just print the progress in R\nrbm \u003c- BM$fitrbm(x, epochs = 20L,\n                 monitoring = function(rbm, epoch) {print(epoch)})\n\n\n# Now real monitoring with callback functions\n# (Abusing environments for call-by-reference value collection)\nmonitor \u003c- new.env(parent = emptyenv())\nmonitor$loglik \u003c- c()\nrbm \u003c- BM$fitrbm(x, epochs = 100L,\n                 monitoring = function(rbm, epoch) {\n                    monitor$loglik \u003c- c(monitor$loglik, BM$loglikelihood(rbm, x))\n                 })\nplot(1:100, monitor$loglik, \"l\")\n\njuliaEval(\"Random.seed!(5);\")\n\n# A complex dbm example with layerwise monitoring\nmonitor \u003c- new.env(parent = emptyenv())\ndbm \u003c- BM$fitdbm(x, epochs = 60L,\n                 learningrate = 0.05,\n                 learningratepretraining = 0.01,\n                 pretraining = list(\n                       BM$TrainLayer(nhidden = 4L, epochs = 70L,\n                              monitoring = function(rbm, epoch) {\n                                 monitor$layer1 \u003c- c(monitor$layer1,\n                                                     BM$reconstructionerror(rbm, x))\n                              }),\n                        BM$TrainLayer(nhidden = 3L, epochs = 50L,\n                              monitoring = function(rbm, epoch) {\n                                 monitor$layer2 \u003c- c(monitor$layer2,\n                                                     BM$reconstructionerror(rbm, x))\n                             })),\n               monitoring = function(dbm, epoch) {\n                  monitor$logproblowerbound \u003c- c(monitor$logproblowerbound,\n                                                 BM$exactloglikelihood(dbm, x))\n               }\n)\nplot(1:70, monitor$layer1, \"l\")\nplot(1:50, monitor$layer2, \"l\")\nplot(1:60, monitor$logproblowerbound, \"l\")\n\n\n# First approach for Gibbs-Sampling, allows access to hidden nodes\nparticles \u003c- BM$initparticles(dbm2, 20L)\nparticles \u003c- BM$`gibbssample!`(particles, dbm2, 100L)\nparticles\n\n# Second approach for Gibbs sampling: All-in-one, returning only visible nodes\nBM$samples(dbm, 5L)\n\n# Conditional Gibbs sampling\nBM$samples(dbm, 5L, conditions = juliaEval(\"[1 =\u003e 1.0, 2 =\u003e 0.0]\"))\n\n\n# A Gaussian-BernoulliRBM\nrbm \u003c- BM$fitrbm(data.matrix(iris[, 1:4]), rbmtype = BM$GaussianBernoulliRBM)\nBM$samples(rbm, 10L)\n```\n\nFor more abstract examples, see the [tests](tests/testthat/test.R).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefan-m-lenz%2FJuliaConnectoR","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstefan-m-lenz%2FJuliaConnectoR","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefan-m-lenz%2FJuliaConnectoR/lists"}