[PYTHON] Create a stacked graph corresponding to both positive and negative directions with matplotlib

Overview

Create a stacked graph ** that corresponds to both the positive and negative directions as shown below.

sample.png

Environment where operation was confirmed

Created and confirmed to work with Google Colab.

python     version 3.6.9
numpy      version 1.18.5
pandas     version 1.1.2
matplotlib version 3.2.2

Preparation

Allows Japanese to be used in matplotlib graphs.

python


!pip install japanize_matplotlib

Load the library.

python


%reset -f
import sys
import pandas as pd
import numpy as np
import japanize_matplotlib
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.patheffects as pe 
pv = '.'.join([ str(v) for v in sys.version_info[:3] ])
print(f'python     version {pv}')
print(f'numpy      version {np.__version__}')
print(f'pandas     version {pd.__version__}')
print(f'matplotlib version {matplotlib.__version__}')

Prepare sample data.

python


df = pd.DataFrame()
df['Classification']=['Middle school students','High school student','College student']
df['Agree']=[10,20,30]
df['If anything, I agree']=[45,50,45]
df['If anything opposite']=[30,20,20]
df['Opposition']=[15,10,5]
display(df)

2020-10-11_21h21_05.png

For this data, "agree" and "somewhat agree" are piled up on the left side, and "somewhat disagree" and "disagree" are piled up on the right side.

code

python


def draw(df, y_column,x_columns,colors,x_range):

  left_columns ,right_columns = x_columns
  left_colors,right_colors = colors

  #Create a 1-by-2 graph
  fig,ax = plt.subplots(nrows=1, ncols=2, figsize=(6,3), facecolor='white',sharey='row',dpi=150)

  #Erase the border
  for a in ax:
    for x in ['top','bottom','left','right']:
      a.spines[x].set_visible(False) 
      a.tick_params(axis='y',left=False) 

  #Graph on the left
  acc = np.zeros(len(df))
  for colum,color in reversed(list(zip(left_columns ,left_colors))):
    s = df[colum]
    ax[0].barh(df[y_column],s,left=acc,color=color,label=colum)
    for i in range(len(df)):
      t = ax[0].text(acc[i]+s[i]/2,i,f'{s[i]}%', ha='center',va='center')
      t.set_path_effects([pe.Stroke(linewidth=3, foreground='white'), pe.Normal()])
    acc+=s

  #Graph on the right
  acc = np.zeros(len(df))
  for colum,color in zip(right_columns,right_colors):
    s = df[colum]
    ax[1].barh(df[y_column],s,left=acc,color=color,label=colum)
    for i in range(len(df)):
      t = ax[1].text(acc[i]+s[i]/2,i,f'{s[i]}%', ha='center',va='center')
      t.set_path_effects([pe.Stroke(linewidth=3, foreground='white'), pe.Normal()])
    acc+=s

  #Usage Guide
  ha,la = ax[0].get_legend_handles_labels()
  ax[0].legend(reversed(ha),reversed(la),bbox_to_anchor=(0.95, 1.05), loc='lower right',ncol=len(left_columns), borderaxespad=0,frameon=False)
  ax[1].legend(bbox_to_anchor=(0.05, 1.05), loc='lower left',ncol=len(right_columns), borderaxespad=0,frameon=False)

  #Draw a line in the center
  ax[1].axvline(x=0,ymin=0,ymax=1,clip_on=False,color='black',lw=1)

  ax[0].set_xlim(x_range[0],0) #The graph on the left flips the X axis
  ax[1].set_xlim(0,x_range[1])

  fig.subplots_adjust(wspace=0.0) #Set the distance between the left and right graphs to zero
  plt.savefig('test.png')
  plt.show()

#Create a graph with sample data
draw(df,'Classification',
     [['Agree','どちらかと言えばAgree'],['If anything opposite','Opposition']],
     [['tab:blue','tab:cyan'],['tab:pink','tab:red']],[80,80])

Execution result

sample.png

Recommended Posts

Create a stacked graph corresponding to both positive and negative directions with matplotlib
Create a graph with borders removed with matplotlib
[Python] How to draw a line graph with Matplotlib
I want to manually create a legend with matplotlib
[Python] How to create a 2D histogram with Matplotlib
I created a stacked bar graph with matplotlib in Python and added a data label
Create a message corresponding to localization with python translation string
[Graph drawing] I tried to write a bar graph of multiple series with matplotlib and seaborn
Draw a loose graph with matplotlib
Write a stacked histogram with matplotlib
Create a word cloud with only positive / negative words on Twitter
I tried to create Bulls and Cows with a shell program
Create a poster with matplotlib to visualize multiplication tables that remember multiplication
I want to create a graph with wavy lines omitted in the middle with matplotlib (I want to manipulate the impression)
How to draw a graph using Matplotlib
(Matplotlib) I want to draw a graph with a size specified in pixels
How to draw a bar graph that summarizes multiple series with matplotlib
Graph trigonometric functions with numpy and matplotlib
Create a Python3 environment with pyenv on Mac and display a NetworkX graph
Use libsixel to output Sixel in Python and output a Matplotlib graph to the terminal.
Zip-compress any file with the [shell] command to create a file and delete the original file.
[Python] How to create a local web server environment with SimpleHTTPServer and CGIHTTPServer
Draw a flat surface with a matplotlib 3d graph
How to draw a 2-axis graph with pyplot
Steps to create a Twitter bot with python
Draw a graph with matplotlib from a csv file
How to create a multi-platform app with kivy
Try to create a battle record table with matplotlib from the data of "Schedule-kun"
Quickly create a Python data analysis dashboard with Streamlit and deploy it to AWS
Steps to quickly create a deep learning environment on Mac with TensorFlow and OpenCV
I tried to create a table only with Django
Create a native GUI app with Py2app and Tkinter
How to create a submenu with the [Blender] plugin
Try to dynamically create a Checkbutton with Python's Tkinter
Create a batch of images and inflate with ImageDataGenerator
Create a 3D model viewer with PyQt5 and PyQtGraph
[Python] How to draw a scatter plot with Matplotlib
[Python] Road to a snake charmer (5) Play with Matplotlib
[Linux] Create a self-signed certificate with Docker and apache
Steps to create a Job that pulls a Docker image and tests it with Github Actions
Steps to set up Pipenv, create a CRUD app with Flask, and containerize it with Docker
How to plot a lot of legends by changing the color of the graph continuously with matplotlib
Band graph with matplotlib
I tried to automatically create a report with Markov chain
How to manage a README for both github and PyPI
Create a web surveillance camera with Raspberry Pi and OpenCV
Create a Mastodon bot with a function to automatically reply with Python
Probably the easiest way to create a pdf with Python3
[pyqtgraph] Add region to the graph and link it with the graph region
Create applications, register data, and share with a single email
Minimum Makefile and buildout.cfg to create an environment with buildout
Try to bring up a subwindow with PyQt5 and Python
Create SVG graph with matplotlib on heroku (displayed in Japanese)
Create a deploy script with fabric and cuisine and reuse it
How to write a metaclass that supports both python2 and python3
[Visualization] I want to draw a beautiful graph with Plotly
How to create dataframes and mess with elements in pandas
I want to create a histogram and overlay the normal distribution curve on it. matplotlib edition
[Python] A data infrastructure for acquiring and publishing tweets from Twitter API to BigQuery was built on GCP (with negative / positive score).