I am trying to have a single data point on a plot legend by following the suggestions here and it does not seem to work:
from pylab import scatter
import pylab
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.gca()
ax.scatter(1,2,c = 'blue', marker = 'x')
ax.scatter(2,3, c= 'red', marker = 'o')
ax.legend(('1','2'), loc = 2, numpoints = 1)
plt.show()
Am I doing something completely stupid here? Some additional information:
In [147]: import matplotlib
print matplotlib.__version__
Out [147]: 1.1.1rc
For scatterplots, use the scatterpoints parameter:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter(1, 2, c='blue', marker='x')
ax.scatter(2, 3, c='red', marker='o')
ax.legend(('1', '2'), loc=2, scatterpoints=1)
plt.show()
Related
I have the following code:
import pandas.util.testing as testing
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl
df = testing.makeTimeDataFrame(freq='MS')
with mpl.rc_context(rc={'font.family': 'serif', 'font.weight': 'bold', 'font.size': 12}):
fig = plt.figure(figsize= (12, 6))
fig.add_subplot(2, 2, (1,2))
ax2 = ax.twinx()
df['A'].plot(ax=ax, color = 'g')
df['B'].plot(ax=ax2, color ='g')
fig.add_subplot(223)
df['C'].plot(color='r')
fig.add_subplot(224)
df['D'].plot()
fig.tight_layout()
plt.show()
Which produces the following plot.
I am trying to plot df['A'] and df['B'] on the same top plot. Could you please advise what I have overlooked?
one little detail is missing. before calling twinx you need to assign ax to the first subplot. Then it'll work.
ax = fig.add_subplot(2, 2, (1,2))
I tried to visualize my data with seaborn.heatmap.
However, the problem I have is that when I print it out in grayscle, the image is hard to read.
I follow many similar questions but it didn't work.
Is there anyway to add hatches over the cells in seaborn.heatmap?
My code is as below:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns
df = pd.read_csv("file.csv")
sns.heatmap(df, annot=False, fmt='.0f', square=True,
cmap="coolwarm", linewidths=1, cbar=False)
plt.show()
You could create a loop, dividing the values into e.g. 4 groups and assign a hatch pattern to each of them via pcolor applied to the subset.
Here is an example starting from random test data:
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
column_names = [f'{c:.2f}' for c in np.arange(0, 1.5001, 0.05)]
row_names = ['Alkaid', 'Mizar', 'Alioth', 'Megrez', 'Phecda', 'Merak', 'Dubhe']
df = pd.DataFrame(np.random.normal(0.3, 1, (len(row_names), len(column_names))).cumsum(axis=1) + 5,
columns=column_names, index=row_names)
values = df.values
vmin = values.min()
vmax = values.max()
patterns = ['', 'oo', '////', 'XXX']
bounds = np.linspace(vmin, vmax, len(patterns) + 1)
bounds[-1] += 1
sns.set_style('white')
fig, ax = plt.subplots(figsize=(12, 5))
sns.heatmap(data=df, linewidths=1, square=True, cmap='coolwarm', linecolor='white', cbar=False, ax=ax)
x = np.arange(df.shape[1] + 1)
y = np.arange(df.shape[0] + 1)
handles = []
norm = plt.Normalize(vmin, vmax)
cmap = plt.get_cmap('coolwarm')
for pattern, b0, b1 in zip(patterns, bounds[:-1], bounds[1:]):
ax.pcolor(x, y, np.where((values >= b0) & (values < b1), values, np.nan), cmap=cmap, norm=norm,
hatch=pattern, ec='black', lw=1)
handles.append(plt.Rectangle((0, 0), 0, 0, color=cmap(norm((b0 + b1) / 2)), ec='black',
hatch=pattern, label=f'{b0:5.2f}-{b1:5.2f}'))
ax.hlines(y, 0, x.max(), color='w', lw=2)
ax.vlines(x, 0, y.max(), color='w', lw=2)
ax.legend(handles=handles, bbox_to_anchor=(1.01, 1.02), loc='upper left',
handlelength=2, handleheight=2, frameon=False)
plt.tight_layout()
plt.show()
Given a line plot obtained with ax.plot(), I have the following handy code to plot the legend on a separate figure:
fig, ax = plt.subplots()
ax.plot([0, 2], label='a', linestyle='--')
ax.plot([-1, 1], label='b', linestyle='dotted')
fig = plt.figure(figsize=(30, 4), constrained_layout=True)
fig.legend(ax.lines, [l.get_label() for l in ax.lines],
loc="upper center")
However if I do this with a histogram (using ax.hist()), ax.lines is empty and I cannot get the labels and styles used. Is it possible to do that still ?
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.random.randn(1000, 3)
colors = ['red', 'tan', 'lime']
_,_,patches = ax.hist(x, 10, color=colors, label=colors)
fig = plt.figure(figsize=(30, 4), constrained_layout=True)
fig.legend([p[0] for p in patches], [p[0].get_label() for p in patches],
loc="upper center")
UPDATE as per comment: you can achieve the same using ax.patches instead of patches returned by ax.hist like so:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.random.randn(1000, 3)
colors = ['red', 'tan', 'lime']
n_bins = 10
ax.hist(x, n_bins, color=colors, label=colors)
fig = plt.figure(figsize=(3, 4), constrained_layout=True)
fig.legend(ax.patches[::n_bins], [p.get_label() for p in ax.patches[::n_bins]], loc="upper center")
Does anyone know why my grid is not plotted on top of the colormap here.
import matplotlib.pylab as plt
import numpy as np
Style = 'ggplot'
plt.style.use([Style])
data = np.random.random((40,40))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.pcolormesh(data, cmap=plt.cm.viridis, zorder=1)
ax.grid(True, zorder=10)
You can use plt.rcParams["axes.axisbelow"] = False to force the grid to be on top. Note that this problem only occurs because of the use of the "ggplot" style.
Example with ggplot style:
import matplotlib.pylab as plt
import numpy as np
plt.style.use('ggplot')
plt.rcParams["axes.axisbelow"] = False
data = np.random.random((40,40))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.pcolormesh(data, cmap=plt.cm.viridis, zorder=1)
ax.grid(True, color="crimson", lw=2)
plt.show()
Example using default style:
import matplotlib.pylab as plt
import numpy as np
data = np.random.random((40,40))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.pcolormesh(data, cmap=plt.cm.viridis, zorder=1)
ax.grid(True, color="crimson", lw=2)
plt.show()
Starting from the following example:
fig, ax = plt.subplots()
df = pd.DataFrame({'n1':[1,2,1,3], 'n2':[1,3,2,1], 'l':['a','b','c','d']})
for label in df['l']:
df.plot('n1','n2', kind='scatter', ax=ax, s=50, linewidth=0.1, label=label)
what I obtained is the following scatterplot:
I'm now trying to set a different color for each of the four points. I know that I can loop over a set of, for instance, 4 colors in a list like:
colorlist = ['b','r','c','y']
but since my real dataset comprise at least 20 different points, I was looking for a sort of "color generator" to loop within it.
The following method will create a list of colors as long as your dataframe, and then plot a point with a label with each color:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors as colors
import numpy as np
import pandas as pd
fig, ax = plt.subplots()
df = pd.DataFrame({'n1':[1,2,1,3], 'n2':[1,3,2,1], 'l':['a','b','c','d']})
colormap = cm.viridis
colorlist = [colors.rgb2hex(colormap(i)) for i in np.linspace(0, 0.9, len(df['l']))]
for i,c in enumerate(colorlist):
x = df['n1'][i]
y = df['n2'][i]
l = df['l'][i]
ax.scatter(x, y, label=l, s=50, linewidth=0.1, c=c)
ax.legend()
plt.show()
IIUC you can do it this way:
import matplotlib.pyplot as plt
from matplotlib import colors
import pandas as pd
colorlist = list(colors.ColorConverter.colors.keys())
fig, ax = plt.subplots()
[df.iloc[[i]].plot.scatter('n1', 'n2', ax=ax, s=50, label=l,
color=colorlist[i % len(colorlist)])
for i,l in enumerate(df.l)]
colorlist:
In [223]: colorlist
Out[223]: ['m', 'b', 'g', 'r', 'k', 'y', 'c', 'w']
PS colorlist[i % len(colorlist)] - should always remain in the list bounds
How about this,
Here is the source code,
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import cm
fig, ax = plt.subplots()
df = pd.DataFrame({'n1':[1,2,1,3], 'n2':[1,3,2,1], 'l':['a','b','c','d']})
#colors = ['b','r','c','y']
nrof_labels = len(df['l'])
colors = cm.rainbow(np.linspace(0, 1, nrof_labels)) # create a bunch of colors
for i, r in df.iterrows():
ax.plot(r['n1'], r['n2'], 'o', markersize=10, color=colors[i], linewidth=0.1, label=r['l'])
ax.set_xlim(0.5, 3.5)
ax.set_ylim(0.5, 3.5)
plt.legend(loc='best')
plt.show()
Additionally, if df[l] has repeated elements and if the colors have to be assigned accordingly:
import matplotlib.cm as cm
import matplotlib.colors as colors
import numpy as np
import pandas as pd
fig, ax = plt.subplots(figsize=(8,8))
df = pd.DataFrame({'n1':[1,2,1,3], 'n2':[1,3,2,1], 'l':['b','b','c','d']})
l_unq = df['l'].unique()
colormap = cm.viridis
colorlist = [colors.rgb2hex(colormap(i)) for i in np.linspace(0, 0.9, len(l_unq))]
for i,c in enumerate(colorlist):
x = df[df.l==l_unq[i]].n1
y = df[df.l==l_unq[i]].n2
l = l_unq[i]
ax.scatter(x, y, label=l, s=50, linewidth=0.1, c=c)
ax.set_xlabel('n1')
ax.set_ylabel('n2')
ax.legend()
plt.show()