how to output a 3 by 3 array to Seaborn chart - python

this is more of a data visualisation issue. I got a 3 by 3 output from my calculations and I want to project the output on to a Seaborn chart for better visual effect. How do I do that? I have attached a random pic of how ideally I would like to see it below. Numbers inside the individual squares will be from my 3*3 array to be clear.
Hypothetical 3*3 array
opt = np.random.randint(1,10,9).reshape(3,3)

You might use seaborn.heatmap. Beyond providing data (2D array), set annot=True if you wish cells to be labeled, simple example:
import numpy as np
import seaborn as sns
data = np.arange(9).reshape(3,3)
ax = sns.heatmap(data, annot=True)
gives

Related

How to plot 1 dimensional data inside the 2 dimensional triangular coordinates with colorbar in python?

I have closed triangle data coordinates a1 (size 10x1) and b1 (10x1), which creates the 3 closed triangles. I have another c1 data (size 3x1). I want to plot the c1 data over the triangle with colorbar. The image I'm attempting to create is similar to the matlab function patch(x,y,c). But I am unable to find a similar function in Python (Jupyter Notebook). Can someone suggest how to plot it?
The following is the sample data:
import numpy as np
import matplotlib.pyplot as plt
a1=[0.90899658,1.10720062,1.47019958,0.90899658,1.47019958,3.14479828,0.90899658,3.14479828,3.17749786,0.90899658]
b1=[-0.38689995,0.22739983,0.69180012,-0.38689995,0.69180012,-0.34249973,-0.38689995,-0.34249973,-0.38329983,-0.38689995]
plt.plot(a1,b1)
#creating triangular matrix of size 3x3 after avoiding last cordinate
a2=a1[0:9]
b2=b1[0:9]
a3=np.reshape(a2,(3,3))
b3=np.reshape(b2,(3,3))
# The data as a third function c1 for 3 triangles
c1=[0.234,0.034,0.006]
# ploting data
plt.fill(a3,b3)
plt.colorbar
The output figure should be like the following (created from Matlab):
I propose the following solution, you can edit the colormap label if you prefer. By the way, I used the following method to display triangles as it was simpler than yours.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
a1=[0.90899658,1.10720062,1.47019958,0.90899658,1.47019958,3.14479828,0.90899658,3.14479828,3.17749786,0.90899658]
b1=[-0.38689995,0.22739983,0.69180012,-0.38689995,0.69180012,-0.34249973,-0.38689995,-0.34249973,-0.38329983,-0.38689995]
# The data as a third function c1 for 3 triangles
c1=[0.234,0.034,0.006]
cmap = mpl.cm.get_cmap('Spectral')
norm = mpl.colors.Normalize(vmin=min(c1), vmax=max(c1))
# ploting data
fig, ax = plt.subplots()
for i in range(0, 9, 3):
atest = np.append(a1[i:i+3], a1[i])
btest = np.append(b1[i:i+3], b1[i])
ax.fill(atest,btest,color=cmap(norm(c1[(int)(i/3)])))
cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap))
plt.show()
Output:

Creating a 2 colour heatmap with Python

I have numerous sets of seasonal data that I am looking to show in a heatmap format. I am not worried about the magnitude of the values in the dataset but more the overall direction and any patterns that i can look at in more detail later. To do this I want to create a heatmap that only shows 2 colours (red for below zero and green for zero and above).
I can create a normal heatmap with seaborn but the normal colour maps do not have only 2 colours and I am not able to create one myself. Even if I could I am unable to set the parameters to reflect the criteria of below zero = red and zero+ = green.
I managed to create this simply by styling the dataframe but I was unable to export it as a .png because the table_criteria='matplotlib' option removes the formatting.
Below is an example of what I would like to create made from random data, could someone help or point me in the direction of a helpful Stackoverflow answer?
I have also included the code I used to style and export the dataframe.
Desired output - this is created with random data in an Excel spreadsheet
#Code to create a regular heatmap - can this be easily amended?
df_hm = pd.read_csv(filename+h)
pivot = df_hm.pivot_table(index='Year', columns='Month', values='delta', aggfunc='sum')
fig, ax = plt.subplots(figsize=(10,5))
ax.set_title('M1 '+h[:-7])
sns.heatmap(pivot, annot=True, fmt='.2f', cmap='RdYlGn')
plt.savefig(chartpath+h[:-7]+" M1.png", bbox_inches='tight')
plt.close()
#code used to export dataframe that loses format in the .png
import matplotlib.pyplot as plt
import dataframe_image as dfi
#pivot is the dateframe name
pivot = pd.DataFrame(np.random.randint(-100,100,size= (5, 12)),columns=list ('ABCDEFGHIJKL'))
styles = [dict(selector="caption", props=[("font-size", "120%"),("font-weight", "bold")])]
pivot = pivot.style.format(precision=2).highlight_between(left=-100000, right=-0.01, props='color:white;background-color:red').highlight_between(left=0, right= 100000, props='color:white;background-color:green').set_caption(title).set_table_styles(styles)
dfi.export(pivot, root+'testhm.png', table_conversion='matplotlib',chrome_path=None)
You can manually set cmap property to list of colors and if you want to annotate you can do it and it will show same value as it's not converted to -1 or 1.
import numpy as np
import seaborn as sns
arr = np.random.randn(10,10)
sns.heatmap(arr,cmap=["grey",'green'],annot=True,center=0)
# center will make it dividing point
Output:
PS. If you don't want color-bar you can pass cbar=False in `sns.heatmap)
Welcome to SO!
To achieve what you need, you just need to pass delta through the sign function, here's an example code:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
arr = np.random.randn(25,25)
sns.heatmap(np.sign(arr))
Which results in a binary heatmap, albeit one with a quite ugly colormap, still, you can fiddle around with Seaborn's colormaps in order to make it look like excel.

How to rotate Seaborn heatmap in python?

default settings of seaborn.heatmap gives
the x-axis starts from the origin of 0 then increases towards the
right
the y-axis starts from an origin of 9 then increases towards the
upward
This is odd compared to matplotlib.pyplot.pcolormesh, which gives a y-axis that starts from an origin of 0 that moves upward, like what we'd intuitively want since it only makes sense for origins to be (0,0), not (0,9)!
How to make the y-axis of heatmap also start from an origin of 0, instead of 9, moving upward? (while of course re-orienting the data correspondingly)
I tried transposing the input data, but this doesn't look right and the axes don't change. I don't think it's a flip about the y-axis that's needed, but a simple rotating of the heatmap.
You can flip the y-axis using ax.invert_yaxis():
import seaborn as sns
import numpy as np
np.random.seed(0)
sns.set_theme()
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data)
ax.invert_yaxis()
If you want to do the rotation you describe, you have to transpose the matrix first:
import seaborn as sns
import numpy as np
np.random.seed(0)
sns.set_theme()
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data.T)
ax.invert_yaxis()
The reason for the difference is that they are assuming different coordinate systems. pcolormesh is assuming that you want to access the elements using cartesian coordinates i.e. [x, y] and it displays them in the way you would expect. heatmap is assuming you want to access the elements using array coordinates i.e. [row, col], so the heatmap it gives has the same layout as if you print the array to the console.
Why do they use different coordinate systems? I would be speculating but I think it's due to the ages of the 2 libraries. matplotlib, particularly its older commands is a port from Matlab, so many of the assumptions are the same. seaborn was developed for Python much later, specifically aimed at statistical visualization, and after pandas was already existent. So I would guess that mwaskom chose the layout to replicate how a DataFrame looks when you print it to the screen.
You can create a graph at the lower left point by resetting yticklabels=[].Does this fit your question?
import seaborn as sns
import numpy as np
np.random.seed(0)
sns.set_theme()
uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, yticklabels=[9,8,7,6,5,4,3,2,1,0])

Is there a 3d plotting function similar to Axes.imshow()?

Ive got test MRI data that I would like to make a 3D plot of. Right now I am visualising each slice individually though using the axes.imshow() function. Is there a 3d equivalent?
Taking the following example, is there anyway to get a black cube out of data in the following example, as opposed to just black square slices of it? That will solve my issue.
Example:
import numpy as np
import matplotlib.pyplot as plt
data = np.zeros((200,200,200))
slice_0 = data[0,:,:]
fig,axes = plt.subplots()
axes.imshow(slice_0.T, cmap="gray")
output

Violin Plot with python

I want to create 10 violin plots but within one diagram. I looked at many examples like this one: Violin plot matplotlib, what shows what I would like to have at the end.
But I did not know how to adapt it to a real data set. They all just generate some random data which is normal distributed.
I have data in form D[10,730] and if I try to adapt it from the link above with :
example:
axes[0].violinplot(all_data,showmeans=False,showmedians=True)
my code:
axes[0].violinplot(D,showmeans=False,showmedians=True)
it do not work.
It should print 10 violin plot in parallel (first dimension of D).
So how do my data need to look like to get the same type of violin plot?
You just need to transpose your data array D.
axes[0].violinplot(D.T,showmeans=False,showmedians=True)
This appears to be a small bug in matplotlib. The axes are treated in a non-consistent manner for a list of 1D arrays and a 2D array.
import numpy as np
import matplotlib.pyplot as plt
n_datasets = 10
n_samples = 730
data = np.random.randn(n_datasets,n_samples)
fig, axes = plt.subplots(1,3)
# http://matplotlib.org/examples/statistics/boxplot_vs_violin_demo.html
axes[0].violinplot([d for d in data])
# should be equivalent to:
axes[1].violinplot(data)
# is actually equivalent to
axes[2].violinplot(data.T)
You should file a bug report.

Categories