Pandas / Plot.plt Line Graph, X Values horizontal - pandas

How can I pass an argument to show all of the x value so one could read it? As well, how can I show many lines of data, and with alegend?
plt. plot(a, b, linewidth=2.0 )

You could display only n-th x-ticks and make a plot bigger to accomodate more labels.
df = pd.DataFrame(data=np.random.rand(10), index=pd.Series(np.random.rand(10)).astype(str)+'_index')
0
0.007017115173211574_index 0.963285
0.434969747965131_index 0.547248
0.18021258326382017_index 0.719402
0.7815848046772174_index 0.061448
0.8856299613744312_index 0.771062
0.16840431221766328_index 0.524256
0.8662531211345982_index 0.528706
0.6389453277004077_index 0.287410
0.7444490769967744_index 0.513631
0.8965709043061524_index 0.892011
plt.subplots(figsize=(20,15)) # make plot bigger
plt.plot(df.index, df[0]*2, linewidth=.9) # plot several lines
plt.plot(df.index, df[0].rename('1'),linewidth=.9) # plot several lines
plt.xticks(df.index[::2]) # tick every 2nd label on x axis.
plt.legend() # show legend

Related

Creating a colorbar in matplotlib given the code below

I'm having a really hard time creating a colourbar given the code below. I had the idea of colouring the lines one by one as my code adds the plot lines for each cycle iteration. What matters is that for each main cycle iteration (i in stim_strength_list) a new line is added for each of the subplots. And the colour values for such line get continuously updated.
Now the issue of such a code is that I'm having an extremely hard time creating a colourbar sitting to the right of all the subplot. Most importantly because I have no ScalarMappable object that can be fed into the plt.colorbar() function. And I don't know of any other function that could get the job done properly.
I see a lot of tutorials on-line where no parameters are given at all to the function and everything works just fine but I don't know why it isn't the case for me. I just began programming recently so I'm really sure that there is something really simple flyin over my head, but despite having searched all over stack overflow I haven't managed to find anything that could fix my specific problem.
stim_strength_list = [int(x)*10 for x in range(0,81)]
stp_list = [int(x) for x in range(51,71)]
area_list = ['V1', 'TO', 'AT', 'PFL', 'PML', 'M1L', 'A1', 'AB', 'PB', 'PFI', 'PMI', 'M1I']
# CREATE THE FIGURE
fig, axis = plt.subplots(2, 6, sharey=True, sharex=True, squeeze=True, figsize=(30, 22.5))
fig.suptitle("Activation plots for each area at different levels of strength, spiking architecture", fontsize=25.0, y=0.99)
# COLOURS
red = 0.0
blue = 1.0
for i in stim_strength_list:
# CREATING VALUES TO BE PLOTTED
a = df_s.drop(df_s[df_s['stim_strength'] != i].index)
b = a.groupby('stp').mean()
for j in area_list: # here a create an empty list for each of the 12 areas
globals()[j]=[] # i.e.: V1 = [], TO = [], AT = [], ...
for j in stp_list: # here I cycle through the time steps..
for k in area_list:
globals()[k].append(b.loc[j, k]) # to append values to each area called upon
# PLOTTING
for row in range(0, 2): # given the plt.subplots() methods refers to the subplots via a matrix coordinate system...
for col in range (0, 6): # ...I use this nested loop to plot values in each list in its respective subplot
if row == 0:
axis[row, col].plot(stp_list, globals()[area_list[col]], color=(red, 0, blue), linewidth=1)
else: # about the col + 6 indexing, if I'm in the second row of the subplots I just add 6 to the current value of col to fetch the appropriate brain area this is just
axis[row, col].plot(stp_list, globals()[area_list[col + 6]], color=(red, 0, blue), linewidth=1)
blue -= 1/len(stim_strength_list) # this is to make it that the first line is fully blue...
red += 1/len(stim_strength_list) # ... and the final one is fully red
# TITLING
for row in range(0, 2): #same logic as above, I did an external nested loop simply because the titling would be done for len(stp_list)*12 times
for col in range (0, 6):
if row == 0:
axis[row, col].set_title(area_list[col], fontsize=25)
else:
axis[row, col].set_title(area_list[col + 6], fontsize=25)
# LABELLING
axis[0, 0].set_ylabel('Amount of cells', fontsize=20)
axis[1, 0].set_ylabel('Amount of cells', fontsize=20)
for i in range(0, 6):
axis[1, i].set_xlabel('Time step', fontsize=20)
fig.tight_layout()
plt.show()
This is the code which creates everything. What is missing is the dataframe from which data is taken but i think that you can get an idea by looking at the result.
Final plot
What I would love to achieve is to have a colorbar which displays the colors employed to color the different lines within each subplot. Such transition is determined by progressively increasing and decreasing the red and blue values within the color attribute in .plot() method.
If I just add plt.colorbar() I will get the following error:
Traceback (most recent call last):
  at block x, line y
  at /opt/python/envs/default/lib/python3.8/site-packages/matplotlib/pyplot.py, line 2084, in colorbar(mappable, cax, ax, **kw)
RuntimeError: No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf).
What would you do with the code available to achieve the result I described above?

Matplotlib: Adding a point to an existing scatterplot that has already been displayed (without needing to recreate)

I'm trying to add a point to a scatterplot that I've already displayed. For simplicity, I'd rather not recreate the plot shown previously, but rather display a previous plot and not have it cleared.
For example: Here is my first plot...
fig, ax = plt.subplots(1,1)
ax.scatter(owners.Income, owners.Lot_Size, marker='o', label='Owner', color='C1')
ax.scatter(nonowners.Income, nonowners.Lot_Size, marker='D', label='Nonowner', color='C0')
plt.xlabel('Income') # set x-axis label
plt.ylabel('Lot_Size') # set y-axis label
# iterate through each row and add the number of each observation to the scatter plot
for index, row in train_data.iterrows(): # look through each row of our data
ax.annotate(index, (row.Income + 1, row.Lot_Size)) # add the number of the observation next to point
handles, labels = ax.get_legend_handles_labels() # add a legend
ax.legend(handles, labels, loc=4)
ax.set_xlim(40, 115) # set the x range
plt.show()
Then, what I'd like to do in the next code cell is to display a new point on this existing figure/ax....
new_household = pd.DataFrame([{'Income': 60, 'Lot_Size': 20}])
new_household
ax.scatter(new_household.Income, new_household.Lot_Size, marker='*', label='New household', color='black', s=150)
plt.show() # nothing displays, since the previous figure is now cleared
The second plot doesn't display because the previous figure has been cleared by the plt.show function.
How can I show the first scatterplot, but keep the figure and ax's so that I can continue add to the plot in later cells (without having to recreate the complete plot each time)?

How can I draw multiple scatter plots in the same cell, in Jupyter Notebook?

I have 3 different dataframes and they all have a 'price' column. I want to have 3 different price to index scatter plots, but I don't want to have them on 3 different cells. I want them to be just in one cell, next to one another.
You should be able to do that in a single cell in Jupyter notebook.
This is probably not the most elegant way to do it, but you'll just need to structure your code so that you draw out each plot in order. e.g. create subplot1, add ticks, labels, etc... plt.show() it, then do the same for all the subsequent plots.
For example:
from matplotlib import pyplot as plt
# First plot
ax = plt.subplot()
plt.scatter( ... ) # Scatter plot 1 data
plt.title( ... )
plt.show()
# Second plot
ax = plt.subplot()
plt.scatter( ... ) # Scatter plot 2 data
plt.title( ... )
plt.show()
# Third plot
# Rinse and repeat

How might I plot multiple lines (same data, different styles) with a single plotting command in matplotlib?

In my example, I want to plot a "highlighting" line (a heavy black line with a narrower yellow line over it to create a black outline) behind the actual data (the blue 'Pitch Angle' line in my example).
My function highlight does this for elements in pandas Series x where h is True and also finally plots x. highlight returns unique identifiers for the highlighting lines created and the actual line styles used to allow the legend entries to be edited to produce what you see in the image, but as far as I can tell that has to be done after all plot commands, i.e. outside of highlight, assuming other things will be added to the Axes e.g. the 'Fine pitch' and '10 degrees' lines in my example.
def highlight(x, h, hlw=8, hc='#FFFBCC', hll='Highlighted', **kwargs):
"""
Plot data in Series x, highlighting the elements correponding to True in h.
"""
# For passing to extra the highlighter lines, drop any passed kwargs which
# would clobber their appearance. Keep a copy of the full set for the data.
# The extra lines are plotted first so they appear underneath the actual
# data.
fullkwargs = kwargs.copy()
for k in ['lw', 'linewidth', 'linestyle', 'ls', 'color', 'c', 'label']:
kwargs.pop(k, None)
# Generate a probably unique ID so that the legend entries of these lines
# can be identified by the caller.
import random
gid = random.random()
# Plot the highlighting lines. First, plot a heavier black line to provide
# a clear outline to the bright highlighted region.
x.where(h).plot(lw=hlw+2, c='k', label='_dont_put_me_in_legend', **kwargs)
# Plot the bright highlighter line on top of that. Give this line an id.
x.where(h).plot(lw=hlw, c=hc, label=hll, gid=gid, **kwargs)
# Plot the actual data.
a = x.plot(**fullkwargs)
# Generate the custom legend entry artists.
import matplotlib.lines as mlines
l1 = mlines.Line2D([], [], lw=hlw+2, c='k')
l2 = mlines.Line2D([], [], lw=hlw, c=hc)
# Return the unique identifier of this call, and the tuple of line styles to
# go to HandlerTuple (see
# http://matplotlib.org/users/legend_guide.html#legend-handlers). This
# makes it possible to update all "highlighter" legend entries with the
# correct color-on-black visual style produced here.
return {gid: (l1, l2)}
I manage to generate an accurate legend entry for the highlighting by making use of HandlerTuple when calling plt.legend() by looping over all legend entries and replacing legend keys where gid is one of the values returned by highlight.
handles,labels = a.get_legend_handles_labels()
newhandles = []
for h in handles:
if h.get_gid() in hi:
newhandles.append(hi[h.get_gid()])
else:
newhandles.append(h)
a.legend(newhandles, labels)
Is there a way in matplotlib to define a "compound" line style such that one plot command produces the desired appearance and has only one legend entry?

discard x-axis label in multi-bar chart in matplotlib

I have produced the graph shown below as intended with matplotlib and Pandas except two problems:
I can't get rid of the x axes labels (Year) for the three plots at the top (things I have tried are commented out in the code attached), and I could not centre the y axis label.
It seem trivial but I can't get it to work.
Any suggestions?
Thanks
fig, axes = plt.subplots(nrows=4, ncols=1, sharex=True, figsize=(12, 12))
for i, crop in enumerate(['Cabbage','Green beans','Potato', 'Wheat']):
mean_irr_soil[crop].plot(kind='bar', ax=axes[i], title=crop, grid=False)
axes[i].set_ylim([0, 700]) # set limit for all y axes
axes[i].tick_params(axis='x', top='off') # remove top ticks
axes[i].tick_params(axis='y', right='off') # remove right-hand ticks
axes[i].tick_params(axis='x', labelbottom='off')
if i is not 0:
axes[i].legend_.remove() # all but top graph
# if i is not 3:
# axes[i].get_xaxis().set_visible(False) # remove axis all together
# axes[i].tick_params(axis='x', labelbottom='off')
# axes[i].set_xticklabels([]) # remove x-axis labels
axes[0].legend(bbox_to_anchor=(1.1, 1.4))
axes[2].set_ylabel('Mean irrigation requirements in mm')
You need the xlabel attribute: ax.set_xlabel("").