WebR 0.2.2+ In Quarto/OJS!
Author
boB Rudis
⏳ WebR is loading…
Also ref the official example.
donatedPlot = Plot.plot({
width: width,
title: "How Many Times Folks Donated To Trump P2024",
marginLeft: 200,
x: {
grid: true,
label: null
},
y: {
label: null
},
marks: [Plot.barX(donated, { x: "n", y: "who", sort: { y: "-x" } })]
})
donated = {
await webR.evalR(`
# working on figuring out how to use the WebR.FS here
trump = read.csv(text = '${await FileAttachment(
"trump-2024-fec.csv"
).text()}', header = TRUE)
linked = read.csv(text = '${await FileAttachment(
"linked-donors.csv"
).text()}', header = TRUE)
trump |>
left_join(
linked, by = "who"
) |>
count(
who,
sort=TRUE
) -> donated
`);
return await getDataFrame(webR, `donated`);
}
{
let svgString = await webR.evalRString(`
s <- svgstring()
ggplot() +
geom_point(
data = mtcars,
aes(wt, mpg)
) -> gg
print(gg)
s()
`);
let document = new DOMParser().parseFromString(svgString, "image/svg+xml");
let svg = d3.select(document.documentElement).remove();
return svg.node();
}
async function R(strings, ...values) {
const [options] = values;
let result = "";
for (let i = 0; i < strings.length; i++) {
result += strings[i];
}
let res, tmp;
if (options === undefined) {
tmp = await webR.evalR(result);
if (typeof tmp == "function") return tmp;
} else {
tmp = await webR.evalR(result, options);
}
res = simplifyRJs(await tmp.toJs());
let ret = res;
return Promise.resolve(ret);
}
function simplifyRJs(obj) {
// if the result is a single char/dbl/bool/int then return a plain value
// if it's an unnamed vector then return a typed array
// if function, return w/o running toJs()
let ret = obj;
console.log(ret);
if (["character", "double", "logical", "integer"].includes(obj.type)) {
if (obj.names === null) {
if (obj.values.length <= 1) {
ret = obj.values[0];
} else {
ret = obj.values;
}
}
}
return ret;
}
async function getDataFrame(ctx, rEvalCode) {
let result = await ctx.evalR(`${rEvalCode}`);
let output = await result.toJs();
return Promise.resolve(webRDataFrameToJS(output));
}
function webRDataFrameToJS(obj) {
return d3.range(0, obj.values[0].values.length).map((ridx) => {
let m = {};
for (var cidx = 0; cidx < obj.names.length; cidx++) {
m[obj.names[cidx]] = obj.values[cidx].values[ridx];
}
return m;
});
}
shelter = {
// Using a webR shelter allows for webR's `captureR` to be used to capture R output
return new webR.Shelter();
}
webR = {
const { WebR, ChannelType } = await import(
"https://cdn.jsdelivr.net/npm/webr/dist/webr.mjs"
);
const intWebR = new WebR({
channelType: ChannelType.PostMessage,
interactive: false
});
await intWebR.init();
// Things seem to work better if you load the pkgs here
await intWebR.installPackages(
["jsonlite", "dplyr", "scales", "ggplot2", "svglite"],
true
);
await intWebR.evalRVoid(`
library(dplyr)
library(ggplot2)
library(svglite)
`);
document.querySelector("#loader").innerText = "🟢";
document.querySelector("#msg").innerText = "WebR loaded!";
return intWebR;
}