I am new to data visualization, so please bear with me.
I am trying to create a data plot that describes various different attributes on a data set on blockbuster movies. The x-axis will be year of the movie and the y-axis will be worldwide gross. Now, some movies have made upwards of a billion in this category, and it seems that my y axis is overwhelmed as it completely blocks out the numbers and becomes illegible. Here is what I have thus far:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv('blockbusters.csv')
fig, ax = plt.subplots()
ax.set_title('Top Grossing Films')
ax.set_xlabel('Year')
ax.set_ylabel('Worldwide Grossing')
x = df['year'] #xaxis
y = df['worldwide_gross'] #yaxis
plt.show()
Any tips on how to scale this down? Ideally it could be presented on a scale of 10. Thanks in advance!
You could try logarithmic scaling:
ax.set_yscale('log')
You might want to manually set the ticks on the y-axis using
ax.set_yticks([list of values for which you want to have a tick])
ax.set_yticklabels([list of labels you want on each tick]) # optional
Another way to approach this might be to rank the movies (which gross is the highest, second highest, ...), i.e. on the y axis you would plot
df['worldwide_gross'].rank()
Edit: as you indicate, one might also check the dtypes to make sure the data is numerical. If not, use .astype(int) or .astype(float) to convert it.
Related
I am trying to plot this DataFrame which records various amounts of money over a yearly series:
from matplotlib.dates import date2num
jp = pd.DataFrame([1000,2000,2500,3000,3250,3750,4500], index=['2011','2012','2013','2014','2015','2016','2017'])
jp.index = pd.to_datetime(jp.index, format='%Y')
jp.columns = ['Money']
I would simply like to make a bar graph out of this using PyPlot (i.e pyplot.bar).
I tried:
plt.figure(figsize=(15,5))
xvals = date2num(jp.index.date)
yvals = jp['Money']
plt.bar(xvals, yvals, color='black')
ax = plt.gca()
ax.xaxis_date()
plt.show()
But the chart turns out like this:
Only by increasing the width substantially will I start seeing the bars. I have a feeling that this graph is attributing the data to the first date of the year (2011-01-01 for example), hence the massive space between each 'bar' and the thinness of the bars.
How can I plot this properly, knowing that this is a yearly series? Ideally the y-axis would contain only the years. Something tells me that I do not need to use date2num(), since this seems like a very common, ordinary plotting exercise.
My guess as to where I'm stuck is not handling the year correctly. As of now I have them as DateTimeIndex, but maybe there are other steps I need to take.
This has puzzled me for 2 days. All solutions I found online seems to use DataFrame.plot, but I would rather learn how to use PyPlot properly. I also intend to add two more sets of bars, and it seems like the most common way to do that is through plt.bar().
Thanks everyone.
You can either do
jp.plot.bar()
which gives:
or plot against the actual years:
plt.bar(jp.index.year, jp.Money)
which gives:
I know it has already been asked, but I could not solve my problem.
I have three pandas column, One with dates, and other with values.
I can get my graph with the two curves depending on date.
However, I cannot display all dates in the x axis. Can you help me?
import pandas as pd
import matplotlib.pyplot as plt
# mau_file is the pandas dataframe with three columns.
plt.figure()
mau_file.plot(x='month_date', y=['mau', 'nb_migs'], figsize=(10,5), grid=True)
plt.set_xticklabels(mau_file['month_date'])
plt.legend(loc='best')
plt.show()
Usually, plt.xticks() is used to display x axis values.
As I'm not sure it is 100% compatible with a pandas structure, you may need to store your data in a classical table or a numpy array.
Documentation of plt.xticks()
EDIT : It is possible to chose the orientation of the labels.
For exemple plt.xticks(x, labels, rotation='vertical') will give you vertical labels.
I am trying to plot a data and function with matplotlib 2.0 under python 2.7.
The x values of the function are evolving with time and the x is first decreasing to a certain value, than increasing again.
If the function is plotted against time, it shows function like this plot of data against time
I need the same x axis evolution for plotting against real x values. Unfortunately as the x values are the same for both parts before and after, both values are mixed together. This gives me the wrong data plot:
In this example it means I need the x-axis to start on value 2.4 and decrease to 1.0 than again increase to 2.4. I swear I found before that this is possible, but unfortunately I can't find a trace about that again.
A matplotlib axis is by default linearly increasing. More importantly, there must be an injective mapping of the number line to the axis units. So changing the data range is not really an option (at least when the aim is to keep things simple).
It would hence be good to keep the original numbers and only change the ticks and ticklabels on the axis. E.g. you could use a FuncFormatter to map the original numbers to
np.abs(x-tp)+tp
where tp would be the turning point.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker
x = np.linspace(-10,20,151)
y = np.exp(-(x-5)**2/19.)
plt.plot(x,y)
tp = 5
fmt = lambda x,pos:"{:g}".format(np.abs(x-tp)+tp)
plt.gca().xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(fmt))
plt.show()
One option would be to use two axes, and plot your two timespans separately on each axes.
for instance, if you have the following data:
myX = np.linspace(1,2.4,100)
myY1 = -1*myX
myY2 = -0.5*myX-0.5
plt.plot(myX,myY, c='b')
plt.plot(myX,myY2, c='g')
you can instead create two subplots with a shared y-axis and no space between the two axes, plot each time span independently, and finally, adjust the limits of one of your x-axis to reverse the order of the points
fig, (ax1,ax2) = plt.subplots(1,2, gridspec_kw={'wspace':0}, sharey=True)
ax1.plot(myX,myY1, c='b')
ax2.plot(myX,myY2, c='g')
ax1.set_xlim((2.4,1))
ax2.set_xlim((1,2.4))
I have some data, based on which I am trying to build a countplot in seaborn. So I do something like this:
data = np.hstack((np.random.normal(10, 5, 10000), np.random.normal(30, 8, 10000))).astype(int)
plot_ = sns.countplot(data)
and get my countplot:
The problem is that ticks on the x-axis are too dense (which makes them useless). I tried to decrease the density with plot_.xticks=np.arange(0, 40, 10) but it didn't help.
Also is there a way to make the plot in one color?
Tick frequency
There seem to be multiple issues here:
You are using the = operator while using plt.xticks. You should use a function call instead (but not here; read point 2 first)!
seaborn's countplot returns an axes-object, not a figure
you need to use the axes-level approach of changing x-ticks (which is not plt.xticks())
Try this:
for ind, label in enumerate(plot_.get_xticklabels()):
if ind % 10 == 0: # every 10th label is kept
label.set_visible(True)
else:
label.set_visible(False)
Colors
I think the data-setup is not optimal here for this type of plot. Seaborn will interpret each unique value as new category and introduce a new color. If i'm right, the number of colors / and x-ticks equals the number of np.unique(data).
Compare your data to seaborn's examples (which are all based on data which can be imported to check).
I also think working with seaborn is much easier using pandas dataframes (and not numpy arrays; i often prepare my data in a wrong way and subset-selection needs preprocessing; dataframes offer more). I think most of seaborn's examples use this data-input.
even though this has been answered a while ago, adding another perhaps simpler alternative that is more flexible.
you can use an matplotlib axis tick locator to control which ticks will be shown.
in this example you can use LinearLocator to achieve the same thing:
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.ticker as ticker
data = np.hstack((np.random.normal(10, 5, 10000), np.random.normal(30, 8, 10000))).astype(int)
plot_ = sns.countplot(data)
plot_.xaxis.set_major_locator(ticker.LinearLocator(10))
Since you have tagged matplotlib, one solution different from setting the ticks visible True/False is to plot every nth label as following
fig = plt.figure(); np.random.seed(123)
data = np.hstack((np.random.normal(10, 5, 10000), np.random.normal(30, 8, 10000))).astype(int)
plot_ = sns.countplot(data)
fig.canvas.draw()
new_ticks = [i.get_text() for i in plot_.get_xticklabels()]
plt.xticks(range(0, len(new_ticks), 10), new_ticks[::10])
As a slight modification of the accepted answer, we typically select labels based on their value (and not index), e.g. to display only values which are divisible by 10, this would work:
for label in plot_.get_xticklabels():
if np.int(label.get_text()) % 10 == 0:
label.set_visible(True)
else:
label.set_visible(False)
I want to change x axis to years. The years are saves in the variable years.
I want to make plot of my data that looks like this:
It should look like this image
However, I am not able to create x axes with a years. My plot looks like the following image:
This is an example of produced image by my code
My code looks as follows:
import pandas as pd
import matplotlib.pyplot as plt
data = pd.read_csv("data1.csv")
demand = data["demand"]
years = data["year"]
plt.plot( demand, color='black')
plt.xlabel("Year")
plt.ylabel("Demand (GW)")
plt.show()
I am thankful for any advice.
The plot method in your example does not know the scaling of your data. So, for simplicity it treats the values of demand as being one unit apart from each other. If you want your x-axis to represent years, you have to tell matplotlib how many values of demand it should treat as "one year". If your data is a monthly demand, it is obviously 12 values per year. And here we go:
# setup a figure
fig, (ax1, ax2) = plt.subplots(2)
# generate some random data
data = np.random.rand(100)
# plot undesired way
ax1.plot(data)
# change the tick positions and labels ...
ax2.plot(data)
# ... to one label every 12th value
xticks = np.arange(0,100,12)
# ... start counting in the year 2000
xlabels = range(2000, 2000+len(xticks))
ax2.set_xticks(xticks)
ax2.set_xticklabels(xlabels)
plt.show()