Quantcast

tornado chart

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

tornado chart

AlanIsaac
I never thought it would happen, but the
Matplotlib Gallery has for once failed me:
http://matplotlib.sourceforge.net/gallery.html

I was looking for an example of creating a nice
tornado chart:
http://code.enthought.com/projects/chaco/docs/html/user_manual/tutorial_1.html
http://www.tushar-mehta.com/excel/software/tornado/
http://www.juiceanalytics.com/writing/recreating-ny-times-cancer-graph/

A basic version will do, say along the lines of
the Chaco example.

Thanks for any leads,
Alan Isaac

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: tornado chart

Tony Yu-3


On Thu, Jun 21, 2012 at 6:42 PM, Alan G Isaac <[hidden email]> wrote:
I never thought it would happen, but the
Matplotlib Gallery has for once failed me:
http://matplotlib.sourceforge.net/gallery.html

I was looking for an example of creating a nice
tornado chart:
http://code.enthought.com/projects/chaco/docs/html/user_manual/tutorial_1.html
http://www.tushar-mehta.com/excel/software/tornado/
http://www.juiceanalytics.com/writing/recreating-ny-times-cancer-graph/

A basic version will do, say along the lines of
the Chaco example.

Thanks for any leads,
Alan Isaac


Hi Alan, 

Here's an example based off the horizontal bar charts in the gallery. There may be a better way to align the y-tick labels (the example manually tweaks the x-offset), but I don't know how to do it off the top of my head. Alternatively, you could put the ticks on the left and squish the space between subplots (using `subplots_adjust(wspace=0)` but then you run into the issue of overlapping x-tick labels.

Hope that helps,
-Tony
 
# tornado chart example
import numpy as np
import matplotlib.pyplot as plt


people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')
num_people = len(people)

time_spent = np.random.uniform(low=5, high=100, size=num_people)
proficiency = np.abs(time_spent / 12. + np.random.normal(size=num_people))
pos = np.arange(num_people) + .5    # bars centered on the y axis

fig, (ax_left, ax_right) = plt.subplots(ncols=2)
ax_left.barh(pos, time_spent, align='center', facecolor='cornflowerblue')
ax_left.set_yticks([])
ax_left.set_xlabel('Hours spent')
ax_left.invert_xaxis()

ax_right.barh(pos, proficiency, align='center', facecolor='lemonchiffon')
ax_right.set_yticks(pos)
# x moves tick labels relative to left edge of axes in axes units
ax_right.set_yticklabels(people, ha='center', x=-0.08)
ax_right.set_xlabel('Proficiency')

plt.suptitle('Learning Python')

plt.show()
 


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: tornado chart

AlanIsaac
On 6/21/2012 10:24 PM, Tony Yu wrote:
> Here's an example based off the horizontal bar charts in the gallery.

Pretty good, really!
More than just a starting point.

Thanks,
Alan



------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: tornado chart

John Hunter-4
On Fri, Jun 22, 2012 at 2:48 PM, Alan G Isaac <[hidden email]> wrote:
> On 6/21/2012 10:24 PM, Tony Yu wrote:
>> Here's an example based off the horizontal bar charts in the gallery.
>
> Pretty good, really!
> More than just a starting point.

And here is a modified example a little closer visually


# tornado chart example; inspired by
# http://www.nytimes.com/imagepages/2007/07/29/health/29cancer.graph.web.html
# and sample code from Tony Yu
import numpy as np
import matplotlib.pyplot as plt

cancers = [
    'Kidney cancer',
    'Bladder cancer',
    'Esophageal cancer',
    'Ovarian cancer',
    'Liver cancer',
    "Non-Hodgkin's\nlymphoma",
    'Leukemia',
    'Prostate cancer',
    'Pancreatic cancer',
    'Breast cancer',
    'Colorectal cancer',
    'Lung cancer',
    ]

num_cancers = len(cancers)

# generate some random data for the graphs (TODO; put real data here)
new_cases_men = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
new_cases_women = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
deaths_women = np.random.rand(num_cancers)*new_cases_women
deaths_men = np.random.rand(num_cancers)*new_cases_men

# force these values where the labels happen to make sure they are
# positioned nicely
new_cases_men[-1] = 120e3
new_cases_men[-2] = 55e3
deaths_men[-1] = 80e3

# bars centered on the y axis
pos = np.arange(num_cancers) + .5

# make the left and right axes for women and men
fig = plt.figure(facecolor='white', edgecolor='none')
ax_women = fig.add_axes([0.05, 0.1, 0.35, 0.8])
ax_men = fig.add_axes([0.6, 0.1, 0.35, 0.8])

ax_men.set_xticks(np.arange(50e3, 201e3, 50e3))
ax_women.set_xticks(np.arange(50e3, 201e3, 50e3))

# turn off the axes spines except on the inside y-axis
for loc, spine in ax_women.spines.iteritems():
    if loc!='right':
        spine.set_color('none') # don't draw spine

for loc, spine in ax_men.spines.iteritems():
    if loc!='left':
        spine.set_color('none') # don't draw spine

# just tick on the top
ax_women.xaxis.set_ticks_position('top')
ax_men.xaxis.set_ticks_position('top')

# make the women's graphs
ax_women.barh(pos, new_cases_women, align='center',
facecolor='#DBE3C2', edgecolor='None')
ax_women.barh(pos, deaths_women, align='center', facecolor='#7E895F',
height=0.5, edgecolor='None')
ax_women.set_yticks([])
ax_women.invert_xaxis()

# make the men's graphs
ax_men.barh(pos, new_cases_men, align='center', facecolor='#D8E2E1',
edgecolor='None')
ax_men.barh(pos, deaths_men, align='center', facecolor='#6D7D72',
height=0.5, edgecolor='None')
ax_men.set_yticks([])

# we want the cancer labels to be centered in the fig coord system and
# centered w/ respect to the bars so we use a custom transform
import matplotlib.transforms as transforms
transform = transforms.blended_transform_factory(
    fig.transFigure, ax_men.transData)
for i, label in enumerate(cancers):
    ax_men.text(0.5, i+0.5, label, ha='center', va='center',
transform=transform)

# the axes titles are in axes coords, so x=0, y=1.025 is on the left
# side of the axes, just above, x=1.0, y=1.025 is the right side of the
# axes, just above
ax_men.set_title('MEN', x=0.0, y=1.025, fontsize=12)
ax_women.set_title('WOMEN', x=1.0, y=1.025, fontsize=12)

# the fig suptile is in fig coords, so 0.98 is the far right; we right
align the text
fig.suptitle('July 29, 2007', x=0.98, ha='right')

# now add the annotations
ax_men.annotate('New Cases', xy=(0.95*new_cases_men[-1], num_cancers-0.5),
                xycoords='data',
                xytext=(20, 0), textcoords='offset points',
                size=12,
                va='center',
                arrowprops=dict(arrowstyle="->"),
                )

# a curved arrow for the deaths annotation
ax_men.annotate('Deaths', xy=(0.95*deaths_men[-1], num_cancers-0.5),
                xycoords='data',
                xytext=(40, -20), textcoords='offset points',
                size=12,
                va='center',
                arrowprops=dict(arrowstyle="->",

connectionstyle="angle,angleA=0,angleB=90,rad=3"),

                )

plt.show()

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

nyt_cancers.png (59K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: tornado chart

Benjamin Root-2


On Friday, June 22, 2012, John Hunter wrote:
On Fri, Jun 22, 2012 at 2:48 PM, Alan G Isaac <<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;alan.isaac@gmail.com&#39;)">alan.isaac@...> wrote:
> On 6/21/2012 10:24 PM, Tony Yu wrote:
>> Here's an example based off the horizontal bar charts in the gallery.
>
> Pretty good, really!
> More than just a starting point.

And here is a modified example a little closer visually


# tornado chart example; inspired by
# http://www.nytimes.com/imagepages/2007/07/29/health/29cancer.graph.web.html
# and sample code from Tony Yu
import numpy as np
import matplotlib.pyplot as plt

cancers = [
   'Kidney cancer',
   'Bladder cancer',
   'Esophageal cancer',
   'Ovarian cancer',
   'Liver cancer',
   "Non-Hodgkin's\nlymphoma",
   'Leukemia',
   'Prostate cancer',
   'Pancreatic cancer',
   'Breast cancer',
   'Colorectal cancer',
   'Lung cancer',
   ]

num_cancers = len(cancers)

# generate some random data for the graphs (TODO; put real data here)
new_cases_men = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
new_cases_women = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
deaths_women = np.random.rand(num_cancers)*new_cases_women
deaths_men = np.random.rand(num_cancers)*new_cases_men

# force these values where the labels happen to make sure they are
# positioned nicely
new_cases_men[-1] = 120e3
new_cases_men[-2] = 55e3
deaths_men[-1] = 80e3

# bars centered on the y axis
pos = np.arange(num_cancers) + .5

# make the left and right axes for women and men
fig = plt.figure(facecolor='white', edgecolor='none')
ax_women = fig.add_axes([0.05, 0.1, 0.35, 0.8])
ax_men = fig.add_axes([0.6, 0.1, 0.35, 0.8])

ax_men.set_xticks(np.arange(50e3, 201e3, 50e3))
ax_women.set_xticks(np.arange(50e3, 201e3, 50e3))

# turn off the axes spines except on the inside y-axis
for loc, spine in ax_women.spines.iteritems():
   if loc!='right':
       spine.set_color('none') # don't draw spine

for loc, spine in ax_men.spines.iteritems():
   if loc!='left':
       spine.set_color('none') # don't draw spine

# just tick on the top
ax_women.xaxis.set_ticks_position('top')
ax_men.xaxis.set_ticks_position('top')

# make the women's graphs
ax_women.barh(pos, new_cases_women, align='center',
facecolor='#DBE3C2', edgecolor='None')
ax_women.barh(pos, deaths_women, align='center', facecolor='#7E895F',
height=0.5, edgecolor='None')
ax_women.set_yticks([])
ax_women.invert_xaxis()

# make the men's graphs
ax_men.barh(pos, new_cases_men, align='center', facecolor='#D8E2E1',
edgecolor='None')
ax_men.barh(pos, deaths_men, align='center', facecolor='#6D7D72',
height=0.5, edgecolor='None')
ax_men.set_yticks([])

# we want the cancer labels to be centered in the fig coord system and
# centered w/ respect to the bars so we use a custom transform
import matplotlib.transforms as transforms
transform = transforms.blended_transform_factory(
   fig.transFigure, ax_men.transData)
for i, label in enumerate(cancers):
   ax_men.text(0.5, i+0.5, label, ha='center', va='center',
transform=transform)

# the axes titles are in axes coords, so x=0, y=1.025 is on the left
# side of the axes, just above, x=1.0, y=1.025 is the right side of the
# axes, just above
ax_men.set_title('MEN', x=0.0, y=1.025, fontsize=12)
ax_women.set_title('WOMEN', x=1.0, y=1.025, fontsize=12)

# the fig suptile is in fig coords, so 0.98 is the far right; we right
align the text
fig.suptitle('July 29, 2007', x=0.98, ha='right')

# now add the annotations
ax_men.annotate('New Cases', xy=(0.95*new_cases_men[-1], num_cancers-0.5),
               xycoords='data',
               xytext=(20, 0), textcoords='offset points',
               size=12,
               va='center',
               arrowprops=dict(arrowstyle="->"),
               )

# a curved arrow for the deaths annotation
ax_men.annotate('Deaths', xy=(0.95*deaths_men[-1], num_cancers-0.5),
               xycoords='data',
               xytext=(40, -20), textcoords='offset points',
               size=12,
               va='center',
               arrowprops=dict(arrowstyle="->",

connectionstyle="angle,angleA=0,angleB=90,rad=3"),

               )

plt.show()


With some real data and a bit of polish to the source, I would love to add this to the gallery.  Real data is a must, of course-- men with ovarian cancer just look silly.

Ben Root 

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: tornado chart

Nicolas Rougier-3


I did it once and posted it to the list but never found the time to add it to the official gallery (my bad):

http://www.loria.fr/~rougier/coding/gallery/showcase/showcase-3-large.png
http://www.loria.fr/~rougier/coding/gallery/


Nicolas





On Jun 23, 2012, at 5:36 , Benjamin Root wrote:

>
>
> On Friday, June 22, 2012, John Hunter wrote:
> On Fri, Jun 22, 2012 at 2:48 PM, Alan G Isaac <[hidden email]> wrote:
> > On 6/21/2012 10:24 PM, Tony Yu wrote:
> >> Here's an example based off the horizontal bar charts in the gallery.
> >
> > Pretty good, really!
> > More than just a starting point.
>
> And here is a modified example a little closer visually
>
>
> # tornado chart example; inspired by
> # http://www.nytimes.com/imagepages/2007/07/29/health/29cancer.graph.web.html
> # and sample code from Tony Yu
> import numpy as np
> import matplotlib.pyplot as plt
>
> cancers = [
>    'Kidney cancer',
>    'Bladder cancer',
>    'Esophageal cancer',
>    'Ovarian cancer',
>    'Liver cancer',
>    "Non-Hodgkin's\nlymphoma",
>    'Leukemia',
>    'Prostate cancer',
>    'Pancreatic cancer',
>    'Breast cancer',
>    'Colorectal cancer',
>    'Lung cancer',
>    ]
>
> num_cancers = len(cancers)
>
> # generate some random data for the graphs (TODO; put real data here)
> new_cases_men = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
> new_cases_women = np.random.uniform(low=20e3, high=200e3, size=num_cancers)
> deaths_women = np.random.rand(num_cancers)*new_cases_women
> deaths_men = np.random.rand(num_cancers)*new_cases_men
>
> # force these values where the labels happen to make sure they are
> # positioned nicely
> new_cases_men[-1] = 120e3
> new_cases_men[-2] = 55e3
> deaths_men[-1] = 80e3
>
> # bars centered on the y axis
> pos = np.arange(num_cancers) + .5
>
> # make the left and right axes for women and men
> fig = plt.figure(facecolor='white', edgecolor='none')
> ax_women = fig.add_axes([0.05, 0.1, 0.35, 0.8])
> ax_men = fig.add_axes([0.6, 0.1, 0.35, 0.8])
>
> ax_men.set_xticks(np.arange(50e3, 201e3, 50e3))
> ax_women.set_xticks(np.arange(50e3, 201e3, 50e3))
>
> # turn off the axes spines except on the inside y-axis
> for loc, spine in ax_women.spines.iteritems():
>    if loc!='right':
>        spine.set_color('none') # don't draw spine
>
> for loc, spine in ax_men.spines.iteritems():
>    if loc!='left':
>        spine.set_color('none') # don't draw spine
>
> # just tick on the top
> ax_women.xaxis.set_ticks_position('top')
> ax_men.xaxis.set_ticks_position('top')
>
> # make the women's graphs
> ax_women.barh(pos, new_cases_women, align='center',
> facecolor='#DBE3C2', edgecolor='None')
> ax_women.barh(pos, deaths_women, align='center', facecolor='#7E895F',
> height=0.5, edgecolor='None')
> ax_women.set_yticks([])
> ax_women.invert_xaxis()
>
> # make the men's graphs
> ax_men.barh(pos, new_cases_men, align='center', facecolor='#D8E2E1',
> edgecolor='None')
> ax_men.barh(pos, deaths_men, align='center', facecolor='#6D7D72',
> height=0.5, edgecolor='None')
> ax_men.set_yticks([])
>
> # we want the cancer labels to be centered in the fig coord system and
> # centered w/ respect to the bars so we use a custom transform
> import matplotlib.transforms as transforms
> transform = transforms.blended_transform_factory(
>    fig.transFigure, ax_men.transData)
> for i, label in enumerate(cancers):
>    ax_men.text(0.5, i+0.5, label, ha='center', va='center',
> transform=transform)
>
> # the axes titles are in axes coords, so x=0, y=1.025 is on the left
> # side of the axes, just above, x=1.0, y=1.025 is the right side of the
> # axes, just above
> ax_men.set_title('MEN', x=0.0, y=1.025, fontsize=12)
> ax_women.set_title('WOMEN', x=1.0, y=1.025, fontsize=12)
>
> # the fig suptile is in fig coords, so 0.98 is the far right; we right
> align the text
> fig.suptitle('July 29, 2007', x=0.98, ha='right')
>
> # now add the annotations
> ax_men.annotate('New Cases', xy=(0.95*new_cases_men[-1], num_cancers-0.5),
>                xycoords='data',
>                xytext=(20, 0), textcoords='offset points',
>                size=12,
>                va='center',
>                arrowprops=dict(arrowstyle="->"),
>                )
>
> # a curved arrow for the deaths annotation
> ax_men.annotate('Deaths', xy=(0.95*deaths_men[-1], num_cancers-0.5),
>                xycoords='data',
>                xytext=(40, -20), textcoords='offset points',
>                size=12,
>                va='center',
>                arrowprops=dict(arrowstyle="->",
>
> connectionstyle="angle,angleA=0,angleB=90,rad=3"),
>
>                )
>
> plt.show()
>
>
> With some real data and a bit of polish to the source, I would love to add this to the gallery.  Real data is a must, of course-- men with ovarian cancer just look silly.
>
> Ben Root
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/_______________________________________________
> Matplotlib-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/matplotlib-users


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users
Loading...