Jupyter Notebook is a flexible tool that helps you create readable analyses which can keep code, images, comments, formulae and plots together. I also would like to make a post to discuss an data analyses result using markdown in my Hexo blog system. In this blog, I will share how to embed the content of Jupyter Notebook into Hexo using markdown format.
Useful Ideas
There are several existing solutions on the Internet:
- .ipynb -> .md -> Copy the content of .md into a Hexo post;
- .ipynb -> .html -> Reference the HTML file in a Hexo post;
- .ipynb -> .html -> Embed the HTML file in a iFrame;
- .ipynb -> .pdf -> Embed the pdf file in a Hexo post using PDF tag.
However, I’m just not satisficed with any of them because of the inconsistent format and style.
My Solution
During my testing, for solution 1, the only biggest problem is Hexo cannot render the DataFrame table very well as it is a raw HTML code in markdown file. Probably we can make it better.
Convert .ipynb to .md
Run the following command to convert .ipynb file from Jupyter Notebook format to a markdown file.1
jupyter nbconvert --to markdown notebook.ipynb
Two new items will be created after running the command:
notebook.md
: a new markdown file;notebook_files
: a folder containing all the images in the notebook.
Embed in a Hexo Post
Create a new post in Hexo and copy the content of notebook.md to the post body.1
2
3
4
5---
layout: '[post]'
title: New Blog Post
---
<Copy the content to here>
Next, move the notebook_files folder to the resource folder of the post. Edit the image tag in Hexo post and point it to correct path.
Fix the DataFrame Table Display Issue
You may notice that DataFrame table is transformed into HTLM format in the markdown file. It seems to be a known issue in Hexo that raw HTLM table code always having problem to be rendered properly. In Hexo, If certain content is causing processing issues, wrap it with the raw
tag to avoid rendering errors. Therefore, To fix the problem, just add a pair of raw
tags to wrap the DataFrame section.1
2
3
4
5
6
7
8
9
10{% raw %}
<div>
<style scoped>
...
</style>
<table border="1" class="dataframe">
...
</table>
</div>
{% endraw %}
Pretty Tables
Next, add some CSS code to format the DataFrame tables appropriately. I’m using Next Theme of Hexo which provides a global option for customized CSS code.
Add the customized CSS code in themes\next\source\css\_costom\custome.styl
. This change will take effect for all DataFrame tables in all posts.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// beauty DataFrame
table.dataframe {
width: 100%;
height: 240px;
display: block;
overflow: auto;
font-family: Arial, sans-serif;
font-size: 13px;
line-height: 20px;
text-align: center;
}
table.dataframe th {
font-weight: bold;
padding: 4px;
border-bottom: 0px;
}
table.dataframe td {
padding: 4px;
border-bottom: 0px;
}
table.dataframe tr:hover {
background: #b8d1f3;
}
Done. Here is a sample DataFrame table:
Total | Percent | |
---|---|---|
PuaMode | 8919174 | 99.974119 |
Census_ProcessorClass | 8884852 | 99.589407 |
DefaultBrowsersIdentifier | 8488045 | 95.141637 |
Census_IsFlightingInternal | 7408759 | 83.044030 |
Census_InternalBatteryType | 6338429 | 71.046809 |
Census_ThresholdOptIn | 5667325 | 63.524472 |
Census_IsWIMBootEnabled | 5659703 | 63.439038 |
SmartScreen | 3177011 | 35.610795 |
OrganizationIdentifier | 2751518 | 30.841487 |
SMode | 537759 | 6.027686 |
CityIdentifier | 325409 | 3.647477 |
Wdft_IsGamer | 303451 | 3.401352 |
Wdft_RegionIdentifier | 303451 | 3.401352 |
Census_InternalBatteryNumberOfCharges | 268755 | 3.012448 |
Census_FirmwareManufacturerIdentifier | 183257 | 2.054109 |
Census_IsFlightsDisabled | 160523 | 1.799286 |
Census_FirmwareVersionIdentifier | 160133 | 1.794915 |
Census_OEMModelIdentifier | 102233 | 1.145919 |
Census_OEMNameIdentifier | 95478 | 1.070203 |
Firewall | 91350 | 1.023933 |
Census_TotalPhysicalRAM | 80533 | 0.902686 |
Census_IsAlwaysOnAlwaysConnectedCapable | 71343 | 0.799676 |
Census_OSInstallLanguageIdentifier | 60084 | 0.673475 |
IeVerIdentifier | 58894 | 0.660137 |
Census_PrimaryDiskTotalCapacity | 53016 | 0.594251 |
Census_SystemVolumeTotalCapacity | 53002 | 0.594094 |
Census_InternalPrimaryDiagonalDisplaySizeInInches | 47134 | 0.528320 |
Census_InternalPrimaryDisplayResolutionHorizontal | 46986 | 0.526661 |
Census_InternalPrimaryDisplayResolutionVertical | 46986 | 0.526661 |
Census_ProcessorModelIdentifier | 41343 | 0.463410 |
Census_ProcessorManufacturerIdentifier | 41313 | 0.463073 |
Census_ProcessorCoreCount | 41306 | 0.462995 |
AVProductsEnabled | 36221 | 0.405998 |
AVProductsInstalled | 36221 | 0.405998 |
AVProductStatesIdentifier | 36221 | 0.405998 |
IsProtected | 36044 | 0.404014 |
RtpStateBitfield | 32318 | 0.362249 |
Census_IsVirtualDevice | 15953 | 0.178816 |
Census_PrimaryDiskTypeName | 12844 | 0.143967 |
UacLuaenable | 10838 | 0.121482 |
Census_ChassisTypeName | 623 | 0.006983 |
GeoNameIdentifier | 213 | 0.002387 |
Census_PowerPlatformRoleName | 55 | 0.000616 |
OsBuildLab | 21 | 0.000235 |
LocaleEnglishNameIdentifier | 0 | 0.000000 |
AvSigVersion | 0 | 0.000000 |
OsPlatformSubRelease | 0 | 0.000000 |
Processor | 0 | 0.000000 |
OsVer | 0 | 0.000000 |
AppVersion | 0 | 0.000000 |
Looks much better.
Reference: