Skip to content

Commit a57a9e5

Browse files
authored
Merge pull request #31 from tdhopper/new-plots
2 parents 67c2030 + 84f2022 commit a57a9e5

4 files changed

Lines changed: 385 additions & 2 deletions

File tree

Examples.ipynb

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,174 @@
698698
"sns.histplot(mpg, x='cty', binwidth=2);"
699699
]
700700
},
701+
{
702+
"cell_type": "markdown",
703+
"metadata": {},
704+
"source": [
705+
"#### Box Plot of a Continuous Value by Category"
706+
]
707+
},
708+
{
709+
"cell_type": "code",
710+
"execution_count": null,
711+
"metadata": {
712+
"tags": [
713+
"ex",
714+
"name:box-plot",
715+
"package:ggplot"
716+
]
717+
},
718+
"outputs": [],
719+
"source": [
720+
"%%R -w 10 -h 10 -u in\n",
721+
"ggplot(data=mpg) +\n",
722+
" aes(x=class, y=hwy) +\n",
723+
" geom_boxplot()"
724+
]
725+
},
726+
{
727+
"cell_type": "code",
728+
"execution_count": null,
729+
"metadata": {
730+
"tags": [
731+
"ex",
732+
"name:box-plot",
733+
"package:pandas"
734+
]
735+
},
736+
"outputs": [],
737+
"source": [
738+
"mpg.boxplot(column='hwy', by='class',\n",
739+
" rot=45);"
740+
]
741+
},
742+
{
743+
"cell_type": "code",
744+
"execution_count": null,
745+
"metadata": {
746+
"tags": [
747+
"ex",
748+
"name:box-plot",
749+
"package:plotnine"
750+
]
751+
},
752+
"outputs": [],
753+
"source": [
754+
"(ggplot(mpg) +\n",
755+
" aes(x=\"class\", y=\"hwy\") +\n",
756+
" geom_boxplot())"
757+
]
758+
},
759+
{
760+
"cell_type": "code",
761+
"execution_count": null,
762+
"metadata": {
763+
"tags": [
764+
"ex",
765+
"name:box-plot",
766+
"package:lets-plot"
767+
]
768+
},
769+
"outputs": [],
770+
"source": [
771+
"(lp.ggplot(mpg) +\n",
772+
" lp.aes(x=\"class\", y=\"hwy\") +\n",
773+
" lp.geom_boxplot())"
774+
]
775+
},
776+
{
777+
"cell_type": "code",
778+
"execution_count": null,
779+
"metadata": {
780+
"tags": [
781+
"ex",
782+
"name:box-plot",
783+
"package:plotly"
784+
]
785+
},
786+
"outputs": [],
787+
"source": [
788+
"px.box(\n",
789+
" mpg, x=\"class\", y=\"hwy\"\n",
790+
")"
791+
]
792+
},
793+
{
794+
"cell_type": "code",
795+
"execution_count": null,
796+
"metadata": {
797+
"tags": [
798+
"ex",
799+
"name:box-plot",
800+
"package:altair"
801+
]
802+
},
803+
"outputs": [],
804+
"source": [
805+
"(\n",
806+
" alt.Chart(mpg)\n",
807+
" .mark_boxplot()\n",
808+
" .encode(x=\"class\", y=\"hwy\")\n",
809+
" .properties(width=400)\n",
810+
")"
811+
]
812+
},
813+
{
814+
"cell_type": "code",
815+
"execution_count": null,
816+
"metadata": {
817+
"tags": [
818+
"ex",
819+
"name:box-plot",
820+
"package:hvplot"
821+
]
822+
},
823+
"outputs": [],
824+
"source": [
825+
"mpg.hvplot.box(y=\"hwy\", by=\"class\",\n",
826+
" rot=45)"
827+
]
828+
},
829+
{
830+
"cell_type": "code",
831+
"execution_count": null,
832+
"metadata": {
833+
"tags": [
834+
"ex",
835+
"name:box-plot",
836+
"package:matplotlib"
837+
]
838+
},
839+
"outputs": [],
840+
"source": [
841+
"\"\"\"`boxplot` takes a list of arrays, so the\n",
842+
"groups are split by hand.\n",
843+
"\"\"\"\n",
844+
"groups = mpg.groupby('class')['hwy']\n",
845+
"fig, ax = pyplot.subplots()\n",
846+
"ax.boxplot([v for _, v in groups],\n",
847+
" tick_labels=list(groups.groups))\n",
848+
"ax.set_xlabel('class')\n",
849+
"ax.set_ylabel('hwy')\n",
850+
"pyplot.xticks(rotation=45);"
851+
]
852+
},
853+
{
854+
"cell_type": "code",
855+
"execution_count": null,
856+
"metadata": {
857+
"tags": [
858+
"ex",
859+
"name:box-plot",
860+
"package:seaborn"
861+
]
862+
},
863+
"outputs": [],
864+
"source": [
865+
"ax = sns.boxplot(mpg, x='class', y='hwy')\n",
866+
"ax.tick_params(axis='x', rotation=45);"
867+
]
868+
},
701869
{
702870
"cell_type": "markdown",
703871
"metadata": {},
@@ -2855,6 +3023,198 @@
28553023
"source": [
28563024
"sns.lineplot(ts, x='date', y='value');"
28573025
]
3026+
},
3027+
{
3028+
"cell_type": "markdown",
3029+
"metadata": {},
3030+
"source": [
3031+
"#### Heatmap of Counts by Two Categories"
3032+
]
3033+
},
3034+
{
3035+
"cell_type": "code",
3036+
"execution_count": null,
3037+
"metadata": {
3038+
"tags": [
3039+
"ex",
3040+
"name:heatmap",
3041+
"package:ggplot"
3042+
]
3043+
},
3044+
"outputs": [],
3045+
"source": [
3046+
"%%R -w 10 -h 10 -u in\n",
3047+
"counts <- as.data.frame(\n",
3048+
" table(cut=diamonds$cut,\n",
3049+
" clarity=diamonds$clarity),\n",
3050+
" responseName=\"count\")\n",
3051+
"ggplot(data=counts) +\n",
3052+
" aes(x=cut, y=clarity, fill=count) +\n",
3053+
" geom_tile()"
3054+
]
3055+
},
3056+
{
3057+
"cell_type": "code",
3058+
"execution_count": null,
3059+
"metadata": {
3060+
"tags": [
3061+
"ex",
3062+
"name:heatmap",
3063+
"package:plotnine"
3064+
]
3065+
},
3066+
"outputs": [],
3067+
"source": [
3068+
"counts = (diamonds\n",
3069+
" .groupby([\"cut\", \"clarity\"])\n",
3070+
" .size()\n",
3071+
" .reset_index(name=\"count\"))\n",
3072+
"(ggplot(counts) +\n",
3073+
" aes(x=\"cut\", y=\"clarity\", fill=\"count\") +\n",
3074+
" geom_tile())"
3075+
]
3076+
},
3077+
{
3078+
"cell_type": "code",
3079+
"execution_count": null,
3080+
"metadata": {
3081+
"tags": [
3082+
"ex",
3083+
"name:heatmap",
3084+
"package:lets-plot"
3085+
]
3086+
},
3087+
"outputs": [],
3088+
"source": [
3089+
"counts = (diamonds\n",
3090+
" .groupby([\"cut\", \"clarity\"])\n",
3091+
" .size()\n",
3092+
" .reset_index(name=\"count\"))\n",
3093+
"(lp.ggplot(counts) +\n",
3094+
" lp.aes(x=\"cut\", y=\"clarity\",\n",
3095+
" fill=\"count\") +\n",
3096+
" lp.geom_tile())"
3097+
]
3098+
},
3099+
{
3100+
"cell_type": "code",
3101+
"execution_count": null,
3102+
"metadata": {
3103+
"tags": [
3104+
"ex",
3105+
"name:heatmap",
3106+
"package:plotly"
3107+
]
3108+
},
3109+
"outputs": [],
3110+
"source": [
3111+
"px.density_heatmap(\n",
3112+
" diamonds, x=\"cut\", y=\"clarity\"\n",
3113+
")"
3114+
]
3115+
},
3116+
{
3117+
"cell_type": "code",
3118+
"execution_count": null,
3119+
"metadata": {
3120+
"tags": [
3121+
"ex",
3122+
"name:heatmap",
3123+
"package:altair"
3124+
]
3125+
},
3126+
"outputs": [],
3127+
"source": [
3128+
"alt.data_transformers.disable_max_rows()\n",
3129+
"(\n",
3130+
" alt.Chart(diamonds)\n",
3131+
" .mark_rect()\n",
3132+
" .encode(\n",
3133+
" x=\"cut\", y=\"clarity\",\n",
3134+
" color=\"count()\",\n",
3135+
" )\n",
3136+
" .properties(width=400, height=400)\n",
3137+
")"
3138+
]
3139+
},
3140+
{
3141+
"cell_type": "code",
3142+
"execution_count": null,
3143+
"metadata": {
3144+
"tags": [
3145+
"ex",
3146+
"name:heatmap",
3147+
"package:hvplot"
3148+
]
3149+
},
3150+
"outputs": [],
3151+
"source": [
3152+
"\"\"\"hvPlot needs the counts up front; `C` names\n",
3153+
"the column that colors each tile.\n",
3154+
"\"\"\"\n",
3155+
"(diamonds\n",
3156+
" .groupby([\"cut\", \"clarity\"])\n",
3157+
" .size()\n",
3158+
" .reset_index(name=\"count\")\n",
3159+
" .hvplot.heatmap(x=\"cut\", y=\"clarity\",\n",
3160+
" C=\"count\", rot=45))"
3161+
]
3162+
},
3163+
{
3164+
"cell_type": "code",
3165+
"execution_count": null,
3166+
"metadata": {
3167+
"tags": [
3168+
"ex",
3169+
"name:heatmap",
3170+
"package:matplotlib"
3171+
]
3172+
},
3173+
"outputs": [],
3174+
"source": [
3175+
"\"\"\"Matplotlib has no heatmap function, so the\n",
3176+
"counts are pivoted and drawn with `pcolormesh`.\n",
3177+
"\"\"\"\n",
3178+
"counts = (diamonds\n",
3179+
" .groupby(['clarity', 'cut'])\n",
3180+
" .size()\n",
3181+
" .unstack())\n",
3182+
"fig, ax = pyplot.subplots()\n",
3183+
"mesh = ax.pcolormesh(counts.values)\n",
3184+
"ax.set_xticks(\n",
3185+
" np.arange(len(counts.columns)) + .5,\n",
3186+
" counts.columns, rotation=45)\n",
3187+
"ax.set_yticks(\n",
3188+
" np.arange(len(counts.index)) + .5,\n",
3189+
" counts.index)\n",
3190+
"ax.set_xlabel('cut')\n",
3191+
"ax.set_ylabel('clarity')\n",
3192+
"fig.colorbar(mesh, label='count');"
3193+
]
3194+
},
3195+
{
3196+
"cell_type": "code",
3197+
"execution_count": null,
3198+
"metadata": {
3199+
"tags": [
3200+
"ex",
3201+
"name:heatmap",
3202+
"package:seaborn"
3203+
]
3204+
},
3205+
"outputs": [],
3206+
"source": [
3207+
"\"\"\"`heatmap` colors a matrix, so the counts are\n",
3208+
"pivoted into one first.\n",
3209+
"\"\"\"\n",
3210+
"counts = (diamonds\n",
3211+
" .groupby(['clarity', 'cut'])\n",
3212+
" .size()\n",
3213+
" .unstack())\n",
3214+
"ax = sns.heatmap(\n",
3215+
" counts, cbar_kws=dict(label='count'))\n",
3216+
"ax.tick_params(axis='y', rotation=0);"
3217+
]
28583218
}
28593219
],
28603220
"metadata": {

INTRO.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ Put the Matplotlib and ggplot2 versions of the two-variable faceted scatter plot
1313

1414
#### Matplotlib-Based Libraries
1515

16-
[Pandas plotting](https://pandas.pydata.org/docs/user_guide/visualization.html "pandas user guide: Chart Visualization") provides "the basics ... to easily create decent looking plots" from data frames. That is about 70% of what I do day-to-day. It has no faceting, no categorical color mapping, and no smoothing, so five of the examples below have no pandas column.
16+
[Pandas plotting](https://pandas.pydata.org/docs/user_guide/visualization.html "pandas user guide: Chart Visualization") provides "the basics ... to easily create decent looking plots" from data frames. That is about 70% of what I do day-to-day. It has no faceting, no categorical color mapping, no smoothing, and no heatmap, so six of the examples below have no pandas column.
1717

1818
Seaborn calls itself "[statistical data visualization](https://seaborn.pydata.org/ "seaborn: statistical data visualization")." Its classic interface is a set of named functions (`histplot`, `scatterplot`, `countplot`, `lmplot`, `kdeplot`) plus [FacetGrid](http://seaborn.pydata.org/tutorial/axis_grids.html), which I use for faceting more than anything else in the library. It covers every plot below, once you know which function to reach for.
1919

20-
Seaborn 0.12 added [seaborn.objects](https://seaborn.pydata.org/tutorial/objects_interface.html), a second interface built on the grammar of graphics. It composes a plot from marks and statistical transforms instead of dispatching to a named plotting function. The interface has no loess smoother and no regression confidence band, so those two examples are missing.
20+
Seaborn 0.12 added [seaborn.objects](https://seaborn.pydata.org/tutorial/objects_interface.html), a second interface built on the grammar of graphics. It composes a plot from marks and statistical transforms instead of dispatching to a named plotting function. The interface has no loess smoother, no regression confidence band, and neither a box-plot nor a rectangle mark, so four of the examples are missing.
2121

2222
"[plotnine](https://plotnine.org/) is a data visualization package for Python based on the grammar of graphics." It tracks ggplot2 closely enough that most R code translates line for line, down to the `+` for layering. I reach for it when I want ggplot2 semantics without leaving Python.
2323

0 commit comments

Comments
 (0)