Plot more than data frame on the same figure pandas - python

I have a list of many aggregated data frames with identical structure.
I would like to plot two columns from each dataframe on the same graph.
I used this code snippet but it gives me a separate plot for each dataframe:
# iterate through a list
for df in frames:
df.plot(x='Time', y='G1', figsize=(16, 10))
plt.hold(True)
plt.show()

If you have each set indexed, you can just concatenate all of them and plot them at once without having to iterate.
# If not indexed:
# frames = [df.assign(sample=i) for i, df in enumerate(frames)]
df = pd.concat(frames).pivot(index='Time', columns='sample', values='G1')
df.plot(figsize=(16, 10));
This helps make sure that your data is aligned and plt.hold is deprecated in matplotlib 2.0.

As you noticed, pandas.DataFrame.plot is not affected by matplotlib's hold parameter because it creates a new figure every time. The way to get around this is to pass in the ax parameter explicitly. If ax is not None, it tells the DataFrame to plot on a specific set of axes instead of making a new figure on its own.
You can prepare a set of axes ahead of time, or use the return value of the first call to df.plot. I show the latter approach here:
ax = None
for df in frames:
ax = df.plot(x='Time', y='G1', figsize=(16, 10), ax=ax)
plt.hold(True)
plt.show()

Related

How to put two Pandas box plots next to each other? Or group them by variable?

I have two data frames (df1 and df2). Each have the same 10 variables with different values.
I created box plots of the variables in the data frames like so:
df1.boxplot()
df2.boxplot()
I get two graphs of 10 box plots next to each other for each variable. The actual output is the second graph, however, as obviously Python just runs the code in order.
Instead, I would either like these box plots to appear side by side OR ideally, I would like 10 graphs (one for each variable) comparing each variable by data frame (e.g. one graph for the first variable with two box plots in it, one for each data frame). Is that possible just using python library or do I have to use Matplotlib?
Thanks!
To get graphs, standard Python isn't enough. You'd need a graphical library such as matplotlib. Seaborn extends matplotlib to ease the creation of complex statistical plots. To work with Seaborn, the dataframes should be converted to long form (e.g. via pandas' melt) and then combined into one large dataframe.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
# suppose df1 and df2 are dataframes, each with the same 10 columns
df1 = pd.DataFrame({i: np.random.randn(100).cumsum() for i in 'abcdefghij'})
df2 = pd.DataFrame({i: np.random.randn(150).cumsum() for i in 'abcdefghij'})
# pd.melt converts the dataframe to long form, pd.concat combines them
df = pd.concat({'df1': df1.melt(), 'df2': df2.melt()}, names=['source', 'old_index'])
# convert the source index to a column, and reset the old index
df = df.reset_index(level=0).reset_index(drop=True)
sns.boxplot(data=df, x='variable', y='value', hue='source', palette='turbo')
This creates boxes for each of the original columns, comparing the two dataframes:
Optionally, you could create multiple subplots with that same information:
sns.catplot(data=df, kind='box', col='variable', y='value', x='source',
palette='turbo', height=3, aspect=0.5, col_wrap=5)
By default, the y-axes are shared. You can disable the sharing via sharey=False. Here is an example, which also removes the repeated x axes and creates a common legend:
g = sns.catplot(data=df, kind='box', col='variable', y='value', x='source', hue='source', dodge=False,
palette='Reds', height=3, aspect=0.5, col_wrap=5, sharey=False)
g.set(xlabel='', xticks=[]) # remove x labels and ticks
g.add_legend()
PS: If you simply want to put two pandas boxplots next to each other, you can create a figure with two subplots, and pass the axes to pandas. (Note that pandas plotting is just an interface towards matplotlib.)
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 5))
df1.boxplot(ax=ax1)
ax1.set_title('df1')
df2.boxplot(ax=ax2)
ax2.set_title('df2')
plt.tight_layout()
plt.show()

Changing Figure Size Bar Plot in Pandas

How would I make the figure larger to clearly display all my values along the y axis.
df = pd.read_csv(io.BytesIO(uploaded['mass_shootings.csv']))
df.State.value_counts().plot(kind='barh')
Try using the figsize argument. E.g.
df = pd.read_csv(io.BytesIO(uploaded['mass_shootings.csv']))
df.State.value_counts().plot(kind='barh', figsize=(20, 6))
Read more on https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html

How to make two separate plots in seaborn from the same dataframe in pandas?

I have a dataframe in pandas that I'm trying to create two separate plots from in the same function, one is an ordinary boxplot w/ jitter and the other is a violin plot.
I've tried saving them to two separate variables and then saving each of those to their own image files, but in each of those files, the plots seem to contain an overlay of both of them rather than each containing their own separate plot. Here's what the code looks like:
final_boxplot = sns.boxplot(data = df)
final_violin = sns.violinplot(data = df)
final_boxplot.figure.savefig('boxplot.png')
final_violin.figure.savefig('violin.png')
any ideas on what I might be doing wrong, or any alternatives?
You should create different instance of figures and
save:
fig,ax = plt.subplots()
sns.boxplot(data=df, ax=ax)
fig.savefig('boxplot.png')
fig, ax = plt.subplots()
sns.violinplot(data=df, ax=ax)
fig.savefig('violin.png')

plotting multiple columns of a pandas dataframe

I am new python and I have two columns in a dataframe that i want to plot against date
plt.scatter(thing.date,thing.loc[:,['numbers','more_numbers']])
my intuition is the above should work (because matlab allows for this kind of thing), but it doesn't, and I'm not sure why.
Is there away around this?
I'm hoping to plot these columns for a sequence of 4 dataframes on the same axes - so i'd like to use a command like the above so I can colour the columns from each data frame to make it distinctive.
Easiest is to do a loop:
fig, ax = plt.subplots()
for col in ['numbers', 'more_numbers']:
ax.scatter(things.date, things[col], label=col)
# or
# things.scatter(x='date', y=col, label=col, ax=ax)
plt.show()

How to remove the extra figures created when running a for loop to create seaborn plots

I am trying to do EDA along with exploring the Matplotlib and Seaborn libraries.
The data_cat DataFrame has 4 columns and I want to create plots in a single row with 4 columns.
For that, I created a figure object with 4 axes objects.
fig, ax = plt.subplots(1,4, figsize = (16,4))
for i in range(len(data_cat.columns)):
sns.catplot(x = data_cat.columns[i], kind = 'count', data = data_cat, ax= ax[i])
The output for it is a figure with the 4 plots (as required) but it is followed by 4 blank plots that I think are the extra figure objects generated by the sns.catplot function.
Your code does not work as intended because sns.catplot() is a figure level function, that is designed to create its own grid of subplots if desired. So if you want to set up the subplot grid directly in matplotlib, as you do with your first line, you should use the appropriate axes level function instead, in this case sns.countplot():
fig, ax = plt.subplots(1, 4, figsize = (16,4))
for i in range(4):
sns.countplot(x = data_cat.columns[i], data = data_cat, ax= ax[i])
Alternatively, you could use pandas' df.melt() method to tidy up your dataset so that all the values from your four columns are in one column (say 'col_all'), and you have another column (say 'subplot') that identifies from which original column each value is. Then you can get all the subplots with one call:
sns.catplot(x='col_all', kind='count', data=data_cat, col='subplot')
I answered a related question here.

Categories