Power BI shows only one patch from Matplotlib patch collection - python

I am trying to show a matplotlib plot in Power BI (desktop). It includes Patchcollection. Running the standalone python code gives this:
But in Power BI, the same code results in this:
Attaching sample code:
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle
import matplotlib.collections
import numpy as np
N = dataset.shape[0]
patches = []
# code to fill in the list patches goes here
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
colors = 100*np.random.random(N)
p = matplotlib.collections.PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4)
p.set_array(colors)
ax.add_collection(p)
plt.autoscale(enable='True', axis='both')
plt.show()
Any help will be appreciated. Thank you!
Edit: Just noticed that the values got doubled for that single patch. Very strange.

Figured out the issue. I had to choose 'Don't Summarize' in the values tab for each field.

Related

How to Create a Real-Time Color Map in Python?

I am trying to create a real-time colour map. I want to continuously change slightly the RGB values of some elements in the matrix to make up my colour map. I read data from an excel file and a part of my data looks like this
Then I want to show the colour change in my colour map in one figure like a video. I tried this code:
df=pd.read_excel(r"G:\3Y_individualProject\Crop_color_data.xlsx", usecols="C:E")
color_data_2d=np.array(df.iloc[0:101])
color_data_1d=np.reshape(color_data_2d,(300))
color_data=color_data_1d.reshape(5,20,3)
for x in range(5):
fig, ax = plt.subplots()
ax.imshow(color_data)
ax.set_aspect("equal")
plt.pause(0.05)
for i in range(3):
color_data[0,1,i]=color_data[0,1,i]+0.1
color_data[1,1,i]=color_data[1,1,i]+0.2
color_data[2,1,i]=color_data[1,1,i]+0.25
print(color_data)
But it plots many different figures instead of showing them in a figure as I expected. I've also just tried to learn and use matplotlib.animation. I have tried the code below:
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import cm
from matplotlib.animation import FuncAnimation
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import itertools
def changeColor(x):
fig, ax = plt.subplots()
ax.imshow(color_data)
ax.set_aspect("equal")
for i in range(3):
color_data[0,1,i]=color_data[0,1,i]+0.1
color_data[1,1,i]=color_data[1,1,i]+0.2
color_data[2,1,i]=color_data[1,1,i]+0.25
results=FuncAnimation(plt.gcf(), changeColor, interval=5)
plt.tight_layout()
plt.show()
But with that code, my figure doesn't even display anything. As said I am quite new to matplotlib.animation so can anyone show me how to use matplotlib.animation or any other way to plot a real-time color map in my case, please? Thank you so much!

How to add multiple histograms in a figure using Matplotlib?

I'm using matplotlib to plot many histograms in one plot successfully:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1)
for i in range(0, 6):
data = np.random.normal(size=1000)
plt.hist(data, bins=30, alpha = 0.5)
plt.show()
However, I wish to export this plot in a pdf, using PdfPages. I want to add each histogram in a separate page, which I successfully do like this:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
np.random.seed(1)
fig = []
with PdfPages("exported_data.pdf") as pdf:
for i in range(0, 6):
data = np.random.normal(size=1000)
fig.append(plt.hist(data, bins=30, alpha = 0.5))
pdf.savefig(fig[i])
plt.close()
But I want another, 7th page with all the plots in one figure as shown above. How do I add many histograms in the same figure (so I can then add in the pdf page)? I see many tutorials on how to plot a grid of histograms within a figure but I haven't found one with all the histograms in one plot added to a figure.
Thanks,
Stam
You can run the loop to plot all histograms together (your first code snippet) after having run the loop to plot them separately (your second code snippet). Here is an example where the random arrays are saved in the datasets list during the first loop to be able to plot them together in the second loop. This solution works by using plt.gcf() which returns the current figure.
import numpy as np # v 1.19.2
import matplotlib.pyplot as plt # v 3.3.4
from matplotlib.backends.backend_pdf import PdfPages
np.random.seed(1)
datasets = []
with PdfPages("exported_data.pdf") as pdf:
# Plot each histogram, adding each figure to the pdf
for i in range(6):
datasets.append(np.random.normal(size=1000))
plt.hist(datasets[i], bins=30, alpha = 0.5)
pdf.savefig(plt.gcf())
plt.close()
# Plot histograms together using a loop then add the completed figure to the pdf
for data in datasets:
plt.hist(data, bins=30, alpha = 0.5)
pdf.savefig(plt.gcf())
plt.close()

Removing or adjusting ticks for inset_axis

TL;DR: I cannot remove or adjust xticks from inset_axis.
I was trying to prepare a zoom-in plot, where a box will display a zoomed version of the plot. However, the x-ticks of the zoomed in plot were too entangled and I decided to manually assign them.
This is a snip from the original plot.
So I tried the following lines:
inset_axe.set_xticks([])
inset_axe.set_yticks([])
It indeed removed the yticks, but xticks are not affected.
Here is a minimum working example. The issue persists in the MWE as well.
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import numpy as np
import matplotlib.pyplot as plt
#####Just creating random N,Q function
a=0.1
Q=np.linspace(-5,4,1000)
M=a*np.ones(2000)
P=1.4**4*np.ones(2000)+a
N=[1.4**(x)+a for x in Q]
N=np.asarray(list(M)+N+list(P))
Q=np.logspace(-9,6,5000)
####################################
g, axes = plt.subplots(1)
inset_axe = inset_axes(axes,width="60%", height="25%", loc='lower left',
bbox_to_anchor=(0.6,0.15,0.7,.7), bbox_transform=axes.transAxes)
inset_axe.semilogx(Q[2200:2400],N[2200:2400])
inset_axe.set_yticks([])
inset_axe.set_xticks([])
axes.semilogx(Q,N)
plt.show()
Is this a bug or do I have a small mistake that I cannot see? Is there a way around this?
If it helps, I use Microsoft VS and matplotlib version is 3.3.3.
Most of your ticks are minor.
You may also want to use the more lightweight axes.inset_axes:
import numpy as np
import matplotlib.pyplot as plt
#####Just creating random N,Q function
a=0.1
Q=np.linspace(-5,4,1000)
M=a*np.ones(2000)
P=1.4**4*np.ones(2000)+a
N=[1.4**(x)+a for x in Q]
N=np.asarray(list(M)+N+list(P))
Q=np.logspace(-9,6,5000)
####################################
g, ax = plt.subplots(1)
inset_axe = ax.inset_axes([0.6, 0.2, 0.2, 0.2], transform=ax.transAxes)
inset_axe.semilogx(Q[2200:2400], N[2200:2400])
inset_axe.set_yticks([])
#################
inset_axe.set_xticks([], minor=True)
#################
inset_axe.set_xticks([])
ax.semilogx(Q,N)
ax.set_xticks([])
plt.show()

How to create legend with proxy artist for contourf plot in Matplotlib

I am trying to create a graphic where I overlay multiple contour plots on a single image. So I want to have colorbars for each of the plots, as well as a legend indicating what each contour represents. However Matplotlib will not allow me to create a separate legend for my contour plots. Simple example:
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
import numpy as np
def create_contour(i,j):
colors = ["red","green","blue"]
hatches = ['-','+','x','//','*']
fig = plt.figure()
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent((-15.0,15.0,-15.0,15.0))
delta = 0.25
x = np.arange(-3.0,3.0,delta)
y = np.arange(-2.0,2.0,delta)
X, Y = np.meshgrid(x, y)
data = np.full(np.shape(X), 1.0)
plot = ax.contourf(X,Y,data, levels = [float(i),float(i+1)], hatch=[hatches[j]], colors = colors[i], label="label")
plt.legend(handles=[plot], labels=["label"])
plt.savefig("figure_"+str(i)+".png")
create_contour(1,3)
When I run this, I get the following message:
UserWarning: Legend does not support
(matplotlib.contour.QuadContourSet object at 0x7fa69df7cac8)
instances. A proxy artist may be used instead. See:
http://matplotlib.org/users/legend_guide.html#creating-artists-specifically-for-adding-to-the-legend-aka-proxy-artists
"aka-proxy-artists".format(orig_handle)
But as far as I can tell, I am following those directions as closely as possible, the only difference being that they do not use contourf in the example.
Any help would be greatly appreciated.
The comments to your question look like they have solved the question (by making custom patches and passing those through to the legend). There is also an example that I added many years ago to the matplotlib documentation to do something similar (about the same time I added contour hatching to matplotlib): https://matplotlib.org/examples/pylab_examples/contourf_hatching.html#pylab-examples-contourf-hatching
It is such a reasonable request that there is even a method on the contour set to give you legend proxies out of the box: ContourSet.legend_elements.
So your example might look something like:
%matplotlib inline
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines('10m')
y = np.linspace(40.0, 60.0, 30)
x = np.linspace(-10.0, 10.0, 40)
X, Y = np.meshgrid(x, y)
data = 2*np.cos(2*X**2/Y) - np.sin(Y**X)
cs = ax.contourf(X, Y, data, 3,
hatches=['//','+','x','o'],
alpha=0.5)
artists, labels = cs.legend_elements()
plt.legend(handles=artists, labels=labels)
plt.show()

Plotting networkx and nxvis graph side by side

I want to plot these two images side by side:
import networkx as nx
import matplotlib.pyplot as plt
import nxviz as nv
test_G = nx.tutte_graph()
nx.draw(test_G)
plt.show()
m = nv.MatrixPlot(test_G)
m.draw()
plt.show()
I tried using:
fig = plt.figure(figsize=(2,1))
sub1 = fig.add_subplot(211)
...
but this creates a new set of axes, is there a standard way to plot images side by side, plt.figure approach seems to work only when I want to create the plot (such as plotting tuples).
nxvis is badly designed. It creates its own hardcoded 111 subplot in a fresh figure. An option may be to first create the nxvis plot and then change its position according to a gridspec.
(Again I haven't tested this, because I cannot install this nxviz package)
import networkx as nx
import matplotlib.pyplot as plt
import nxviz as nv
import matplotlib.gridspec
test_G = nx.tutte_graph()
m = nv.MatrixPlot(test_G)
m.draw()
gs = matplotlib.gridspec.GridSpec(2,1)
plt.gca().set_position(gs[1].get_position(plt.gcf()))
plt.gca().set_subplotspec(gs[1])
plt.subplot(gs[0])
nx.draw(test_G)
plt.show()

Categories

Resources