In Rmarkdown documents there is a code folding option--code_folding: hide. This option is not available for Hugo websites generated with the blogdown package (see this recently opened feature request). Has anyone come up with a work-around for this? Even some JavaScript and HTML code that can be added on a post-by-post basis?
As an example, blogdown generates a default Hugo site with the Hugo-lithium theme when you run the following command in an new directory:
blogdown::new_site().
One of the posts generated for this default is below. I'd be interested in adding code folding to this example, that is, a hide/show button that the webpage above each R code block.
title: "Hello R Markdown"
author: "Frida Gomam"
date: 2015-07-23T21:13:14-05:00
categories: ["R"]
tags: ["R Markdown", "plot", "regression"]
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE)
```
# R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
You can embed an R code chunk like this:
```{r cars}
summary(cars)
fit <- lm(dist ~ speed, data = cars)
fit
```
# Including Plots
You can also embed plots. See Figure \#ref(fig:pie) for example:
```{r pie, fig.cap='A fancy pie chart.', tidy=FALSE}
par(mar = c(0, 1, 0, 1))
pie(
c(280, 60, 20),
c('Sky', 'Sunny side of pyramid', 'Shady side of pyramid'),
col = c('#0292D8', '#F7EA39', '#C4B632'),
init.angle = -50, border = NA
)
Related
tl;dr - After exporting a Google Doc as an HTML file and pasting the HTML into a GMail draft it does not contain the formatting from the original Google Doc (other than hyperlinks).
Code snippet:
//copies the doc to HTML format
var htmlExport = "https://docs.google.com/feeds/download/documents/export/Export?id=" + docID + "&exportFormat=html";
var param = {
method: "get",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
};
var htmlExportText = UrlFetchApp.fetch(htmlExport,param).getContentText();
//the variables below (contactEmail & emailSubject) are both taken from a spreadsheet
//copies recent draft body to new email, then updates body of new email to include HTML export
var draftEmailBody = GmailApp.getMessageById(draftEmailID).getBody();
var draftToSend = GmailApp.createDraft(contactEmail,emailSubject,'',{htmlBody: htmlExportText + draftEmailBody}).getMessageId();
Long version:
I am building a mail merge that pulls contact info from a GSheet and uses GDoc as the template for the body. The GDoc has several bits of formatting in it (bold, italics, superscript) that, when exported as an HTML using the script above, appear in the GMail draft devoid of formatting (for some reason it leaves the hyperlinks). For some odd reason it even leaves the images from the doc!
The GMail draft pulled into the body (draftEmailBody) does, however, keep all it's formatting. I can only assume this means I'm doing something wrong by using getContentText but I don't know how else to go about it.
(This is completely separate and I should probably just make another question for this, but I'm here so...)
Separately, I wanted to have the script edit specific fields within the GDoc template, but I have run into 2 issues.
Problem 1 - I have found no way to replace specific text within a GMail draft.
Workaround 1 - I have the script edit the text in a GDoc instead, using repalceText. This, however, leads to:
Problem 2 - Using replaceText in a GDoc requires you to saveAndClose before the script can recognize the change. For some reason I can never get my script to open the GDoc again, despite including openByID in various places of the script!
Workaround 2 - I create a copy of the doc for each contact, replacing the text within that doc, then trash all of the copies on completion so there's no clutter. Quite clunky and slow but it gets the job done.
While it's not the prettiest solution, I found something that helps:
Google Scripts: Generating Email from Docs Loses Formatting
I'm using plotly library in offline mode with python and what I'm trying to do is to create some plot, save them as local html and load in a second moment into a QWebView.
This is the code for a boxplot with a dummy variable:
from PyQt5.QtWebKitWidgets import QWebView
import plotly
import plotly.graph_objs as go
x1 = [10, 3, 4, 5, 20, 4, 3]
trace1 = go.Box(
x = x1)
layout = go.Layout(
showlegend = True
)
data = [trace1]
fig = go.Figure(data=data, layout = layout)
fn = '/home/matteo/plot.html'
plotly.offline.plot(fig, filename = fn,
auto_open = False)
view = QWebView()
view.load(QUrl.fromLocalFile(fn))
view.show()
I'm facing 2 main problems:
if I let the code as it is, the QWebView won't show anything like in the image:
if I open the html file with the standard browser (Firefox for example), I can see and interact with the plot, and that's fine. But if I save the html page from the browser in a local directory and try to load the saved file into the QWebView I can see the plot, but cannot interact with it (maybe for some Javascript missing?!):
Anybody has some ideas how to embed an interactive offline made chart into a QWebView?
Ok, I should have find what the problem is.
Is seems that QWebView has some difficulties to load the local file because it is too heavy (about 2mb for simple plot).
So I used the option to not include the javascript when saving the local file and to load the javascript in a second moment thanks, as described here.
In other words, create the initial html tags, include the result of the figure generated by plotly without the whole javascript code, and include the link of the javascript.
In this way the file is super light and QWebView does not have issue to open it.
# create the initial html code
raw_html = '<head><meta charset="utf-8" /></head>''<head><meta charset="utf-8" /><script src="https://cdn.plot.ly/plotly-latest.min.js"></script></head>'
# call the plot method without all the javascript code
raw_html += plotly.offline.plot(fig, filename = fn, include_plotlyjs=False)
# close the body and html tags
raw_html += '</body></html>'
Is it possible to add click events to a Plotly scatter plot (offline mode in Python)?
As an example, I want to change the shape of a set of scatter points upon being clicked.
What I tried so far
My understanding from reading other questions from the site (with no clear answer) is that I may have to produce the html and then edit it after the fact by putting in javascript code? So I could write a javascript function, save it off to my_js.js and then link to it from the html?
I've been doing some work with offline plots in plotly and had the same challenge.
Here's a kludge I've come up with which my prove as inspiration for others.
Some limitations:
Assumes that you have the offline output in a single html file, for a single plot.
Assumes that your on events are named the same as the event handlers.
Requires Beautiful Soup 4.
Assumes you've got lxml installed.
Developed with Plotly 2.2.2
Code Snippet:
import bs4
def add_custom_plotly_events(
filename,
events = {
"plotly_click": "function plotly_click(data) { console.log(data); }",
"plotly_hover": "function plotly_hover(data) { console.log(data); }"
},
prettify_html = True
):
# what the value we're looking for the javascript
find_string = "Plotly.newPlot"
# stop if we find this value
stop_string = "then(function(myPlot)"
def locate_newplot_script_tag(soup):
scripts = soup.find_all('script')
script_tag = soup.find_all(string=re.compile(find_string))
if len(script_tag) == 0:
raise ValueError("Couldn't locate the newPlot javascript in {}".format(filename))
elif len(script_tag) > 1:
raise ValueError("Located multiple newPlot javascript in {}".format(filename))
if script_tag[0].find(stop_string) > -1:
raise ValueError("Already updated javascript, it contains:", stop_string)
return script_tag[0]
def split_javascript_lines(new_plot_script_tag):
return new_plot_script_tag.string.split(";")
def find_newplot_creation_line(javascript_lines):
for index, line in enumerate(javascript_lines):
if line.find(find_string) > -1:
return index, line
raise ValueError("Missing new plot creation in javascript, couldn't find:", find_string)
def join_javascript_lines(javascript_lines):
# join the lines with javascript line terminator ;
return ";".join(javascript_lines)
def register_on_events(events):
on_events_registration = []
for function_name in events:
on_events_registration.append("myPlot.on('{}', {})".format(
function_name, function_name
))
return on_events_registration
# load the file
with open(filename) as inf:
txt = inf.read()
soup = bs4.BeautifulSoup(txt, "lxml")
new_plot_script_tag = locate_newplot_script_tag(soup)
javascript_lines = split_javascript_lines(new_plot_script_tag)
line_index, line_text = find_newplot_creation_line(javascript_lines)
on_events_registration = register_on_events(events)
# replace whitespace characters with actual whitespace
# using + to concat the strings as {} in format
# causes fun times with {} as the brackets in js
# could possibly overcome this with in ES6 arrows and such
line_text = line_text + ".then(function(myPlot) { " + join_javascript_lines(on_events_registration) +" })".replace('\n', ' ').replace('\r', '')
# now add the function bodies we've register in the on handles
for function_name in events:
javascript_lines.append(events[function_name])
# update the specific line
javascript_lines[line_index] = line_text
# update the text of the script tag
new_plot_script_tag.string.replace_with(join_javascript_lines(javascript_lines))
# save the file again
with open(filename, "w") as outf:
# tbh the pretty out is still ugly af
if prettify_html:
for line in soup.prettify(formatter = None):
outf.write(str(line))
else:
outf.write(str(soup))
According to Click events in python offline mode? on Plotly's community site this is not supported, at least as of December 2015.
That post does contain some hints as to how to implement this functionality yourself, if you're feeling adventurous.
At work I'd like to parse some web pages. Unfortunately I can't add any real page to my example because the urls at work are confident. I can only try to explain what is the problem.
To parse I wrote the following script in R. As a mock url I used www.imdb.com.:
library(rvest)
library(plyr)
# urls
url <- "http://www.imdb.com/"
# parse
html <- try(read_html(url))
# select
select_meta <- function(html) {
html %>%
html_nodes(xpath = "//div") %>%
html_attrs # function to select meta
}
meta <- select_meta(html)
Problem is this script doesn't return anything for the pages I use at work. I guess this is because the scripts are generated by javascript. I found this tutorial which explains how to scrape javascript generated pages in R.
The code used to generate the page in the tutorial is the following:
// scrape_techstars.js
var webPage = require('webpage');
var page = webPage.create();
var fs = require('fs');
var path = 'techstars.html'
page.open('http://www.techstars.com/companies/stats/', function (status) {
var content = page.content;
fs.write(path,content,'w')
phantom.exit();
});
I don't have any Javascript knowledge so I'm having trouble scaling page.open (which only works for 1 page) to multiple pages (at work I have to parse roughly 100 pages). So instead of relying on phantom js I'd rather have a solution which is completely R based (if this is totally inefficient and offensive to real coders, I apologise in advance). So the crux of my question is: "how can I generate several pages in R?".
This is a one-off thing so I'm not really thinking about reading up on Javascript or parsing. Thanks in advance for helping me out.
I want to do a pie chart in matplotlib.
This pie chart will be a representation of two variables: male and female.
That's easy to do :)
What I would like to do next, I'm not even sure if it's possible to do with matplotlib, I would like to make these two variables clickable so if I click on male, I would see another page with information about this, same thing with female.
Image map isn't a solution since this variables may change in the future.
Anyone has any idea how to do this? If it's possible with matplotlib or what program would you recommend.
Thank you!
While it's not really in a workably stable state yet, have a look at the html5 canvas backend for matplotlib. It looks interesting, anyway, and will probably be the best way to do this sort of thing (interactive webpage with a matplotlib plot) in the future.
In the meantime, as #Mark suggested, it's not too hard to dynamically generate an imagemap for the wedges of a pie plot.
Here's a rough example, that I'm sure you could adapt to whatever web framework you're using.
import matplotlib.pyplot as plt
def main():
# Make an example pie plot
fig = plt.figure()
ax = fig.add_subplot(111)
labels = ['Beans', 'Squash', 'Corn']
wedges, plt_labels = ax.pie([20, 40, 60], labels=labels)
ax.axis('equal')
make_image_map(fig, wedges, labels, 'temp.html')
def make_image_map(fig, wedges, labels, html_filename):
"""Makes an example static html page with a image map of a pie chart.."""
#-- Save the figure as an image and get image size ------------------------
# Be sure to explictly set the dpi when saving the figure
im_filename = 'temp.png'
fig.savefig(im_filename, dpi=fig.dpi)
# Get figure size...
_, _, fig_width, fig_height = fig.bbox.bounds
#-- Get the coordinates of each wedge as a string of x1,y2,x2,y2... -------
coords = []
for wedge in wedges:
xy = wedge.get_verts()
# Transform to pixel coords
xy = fig.get_transform().transform(xy)
# Format into coord string and convert to <0,0> in top left...
xy = ', '.join(['%0.2f,%0.2f' % (x, fig_height - y) for x, y in xy])
coords.append(xy)
#-- Build web page --------------------------------------------------------
header = """
<html>
<body>
<img src="{0}" alt="Pie Chart" usemap="#pie_map" width="{1}" height="{2}" />
""".format(im_filename, fig_width, fig_height)
# Make the image map
map = '<map name="pie_map">\n'
for label, xy in zip(labels, coords):
href = 'http://images.google.com/images?q={0}'.format(label)
area = '<area shape="poly" coords="{0}" href="{1}" alt="{2}" />'
area = area.format(xy, href, label)
map += ' ' + area + '\n'
map += '</map>\n'
footer = """
</body>
</html>"""
# Write to a file...
with file(html_filename, 'w') as outfile:
outfile.write(header + map + footer)
if __name__ == '__main__':
main()
Edit: I just realized that you might not be referring to embedding the plot into a web page... (I assumed that you were from the "display another page" bit in your question.) If you want more of a desktop app, without having to mess with a "full" gui toolkit, you can do something like this:
import matplotlib.pyplot as plt
def main():
# Make an example pie plot
fig = plt.figure()
ax = fig.add_subplot(111)
labels = ['Beans', 'Squash', 'Corn']
wedges, plt_labels = ax.pie([20, 40, 60], labels=labels)
ax.axis('equal')
make_picker(fig, wedges)
plt.show()
def make_picker(fig, wedges):
import webbrowser
def on_pick(event):
wedge = event.artist
label = wedge.get_label()
webbrowser.open('http://images.google.com/images?q={0}'.format(label))
# Make wedges selectable
for wedge in wedges:
wedge.set_picker(True)
fig.canvas.mpl_connect('pick_event', on_pick)
if __name__ == '__main__':
main()
Which opens a browser window for a google image search of whatever the wedge is labeled as...
You can do this with an imagemap or HTML element overlay controlled by JavaScript/jQuery.
Essentially, send your chart data to the page along with the chart image, and use JS to create the elements with the links according to the specification of the data.
It's a bit harder than the bar graphs I've done this to before, but should work fine.