How to filter data while drawing? - python

I have a dataframe which I drawed as you can see the figure and codes below;
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
df = pd.read_excel('nötronn.xlsx')
fig, ax = plt.subplots(figsize=(20,40))
ax1 = plt.subplot2grid((1,5), (0,0), rowspan=1, colspan = 1)
ax1.plot(df["N/F*10"], df['Depth'], color = "green", linewidth = 0.5)
ax1.set_xlabel("Porosity")
ax1.xaxis.label.set_color("green")
ax1.set_xlim(10, 50)
ax1.set_ylabel("Depth (m)")
ax1.tick_params(axis='x', colors="green")
ax1.spines["top"].set_edgecolor("green")
ax1.title.set_color('green')
ax1.set_xticks([10, 20, 30, 40, 50])
I want to filter data so that I can realize the differences better. I tried these:
z = np.polyfit(df["N/F*10"], df['Depth'], 2)
p = np.poly1d(z)
plt.plot(df["N/F*10"], p(df["N/F*10"]))
But it gives :LinAlgError: SVD did not converge in Linear Least Squares
How can I solve it? Thanks.
Output expectation:

This works!
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from statsmodels.nonparametric.smoothers_lowess import lowess
data = pd.read_excel('nötronn.xlsx')
sub_data = data[data['Depth'] > 21.5]
result = lowess(sub_data['Eksi'], sub_data['Depth'].values)
x_smooth = result[:,0]
y_smooth = result[:,1]
tot_result = lowess(data['Eksi'], data['Depth'].values, frac=0.01)
x_tot_smooth = tot_result[:,0]
y_tot_smooth = tot_result[:,1]
fig, ax = plt.subplots(figsize=(20, 8))
##ax.plot(data.depth.values, data['N/F*10'], label="raw")
ax.plot(x_tot_smooth, y_tot_smooth, label="lowess 1%", linewidth=3, color="g")
ax.plot(data['GR-V121B-ETi'])
ax.plot(data['Caliper'], linestyle = 'dashed')

Related

add legend seaborn barplot

Here is my code :
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
array = np.array([[1,5,9],[3,5,7]])
df = pd.DataFrame(data=array, index=['Positive', 'Negative'])
f, ax = plt.subplots(figsize=(8, 6))
current_palette = sns.color_palette('colorblind')
ax_pos = sns.barplot(x = np.arange(0,3,1), y = df.loc['Positive'].to_numpy(), color = current_palette[2], alpha = 0.66)
ax_neg = sns.barplot(x = np.arange(0,3,1), y = df.loc['Negative'].to_numpy(), color = current_palette[4], alpha = 0.66)
plt.xticks(np.arange(0,3,1), fontsize = 20)
plt.yticks(np.arange(0,10,1), fontsize = 20)
plt.legend((ax_pos[0], ax_neg[0]), ('Positive', 'Negative'))
plt.tight_layout()
Unfortunately, I have this error :
TypeError: 'AxesSubplot' object does not support indexing
I would like to know why calling legend like this (plt.legend(ax[0]...) is not possible with seaborn whereas with matplotlib it is.
In the end, I just want the legend in the upper left corner.
I figured out that barplot has "label" function :
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
array = np.array([[1,5,9],[3,5,7]])
df = pd.DataFrame(data=array, index=['Positive', 'Negative'])
f, ax = plt.subplots(figsize=(8, 6))
current_palette = sns.color_palette('colorblind')
sns.barplot(x = np.arange(0,3,1), y = df.loc['Positive'].to_numpy(), color = current_palette[2], alpha = 0.66, label = "Positive")
sns.barplot(x = np.arange(0,3,1), y = df.loc['Negative'].to_numpy(), color = current_palette[4], alpha = 0.66, label = "Negative")
plt.xticks(np.arange(0,3,1), fontsize = 20)
plt.yticks(np.arange(0,10,1), fontsize = 20)
plt.legend(frameon = False)
plt.tight_layout()

Remove lowest color from colorbar in Seaborn/Matplotlib

If I set shade_lowest = False, the colorbar still contains the lowest level (purple-ish). Is there any generic way to remove it entirely?
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
a = np.random.normal(0, 1, 100)
b = np.random.normal(0, 1, 100)
fig, ax = plt.subplots()
sns.kdeplot(a, b, shade = True, shade_lowest = False, cmap = "viridis", cbar = True, n_levels = 4, ax = ax)
plt.show()
A solution is for sure to not create this level from the beginning.
Here we choose maximally 5 levels according to a locator and remove the lowest one when calling the contourf plot, such that this level does not even exist in the first place. Then the automatic colorbar creation works flawlessly.
import numpy as np; np.random.seed(5)
import matplotlib.pyplot as plt
from matplotlib import ticker
from scipy import stats
x = np.random.normal(3, 1, 100)
y = np.random.normal(0, 2, 100)
X, Y = np.mgrid[x.min():x.max():100j, y.min():y.max():100j]
positions = np.vstack([X.ravel(),Y.ravel()])
values = np.vstack([x,y])
kernel = stats.gaussian_kde(values)
Z = np.reshape(kernel(positions).T, X.shape)
N=4
locator = ticker.MaxNLocator(N + 1, min_n_ticks=N)
lev = locator.tick_values(Z.min(), Z.max())
fig, ax = plt.subplots()
c = ax.contourf(X,Y,Z,levels=lev[1:])
ax.scatter(x,y, s=9, c="k")
fig.colorbar(c)
plt.show()

display matrix values and colormap

I need to display values of my matrix using matshow.
However, with the code I have now I just get two matrices - one with values and other colored.
How do I impose them? Thanks :)
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
min_val, max_val = 0, 15
for i in xrange(15):
for j in xrange(15):
c = intersection_matrix[i][j]
ax.text(i+0.5, j+0.5, str(c), va='center', ha='center')
plt.matshow(intersection_matrix, cmap=plt.cm.Blues)
ax.set_xlim(min_val, max_val)
ax.set_ylim(min_val, max_val)
ax.set_xticks(np.arange(max_val))
ax.set_yticks(np.arange(max_val))
ax.grid()
Output:
You need to use ax.matshow not plt.matshow to make sure they both appear on the same axes.
If you do that, you also don't need to set the axes limits or ticks.
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
min_val, max_val = 0, 15
intersection_matrix = np.random.randint(0, 10, size=(max_val, max_val))
ax.matshow(intersection_matrix, cmap=plt.cm.Blues)
for i in xrange(15):
for j in xrange(15):
c = intersection_matrix[j,i]
ax.text(i, j, str(c), va='center', ha='center')
Here I have created some random data as I don't have your matrix. Note that I had to change the ordering of the index for the text label to [j,i] rather than [i][j] to align the labels correctly.
In Jupyter notebooks this is also possible with DataFrames and Seaborn:
import numpy as np
import seaborn as sns
import pandas as pd
min_val, max_val = 0, 15
intersection_matrix = np.random.randint(0, 10, size=(max_val, max_val))
cm = sns.light_palette("blue", as_cmap=True)
x=pd.DataFrame(intersection_matrix)
x=x.style.background_gradient(cmap=cm)
display(x)

Python Matplotlib - imshow but with hexagons

Code is:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
example_data = np.random.randint(4, size=(40,44))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)
img = plt.imshow(example_data, interpolation = 'nearest', origin = 'lower',
cmap = cmap, norm = norm)
Which gets me roughly what I want. What I am looking for is if there is a way to get the shape of each tile to be hexagonal rather than square? I think imshow might not be the way to do it but if there is a way you can change the default tile it would be good.
Thanks.
Here is a solution using patches:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection
nx = 40
ny = 44
example_data = np.random.randint(4, size=(nx,ny))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)
x = np.linspace(0, 1, nx)
y = np.linspace(0, 1, ny)
X, Y = np.meshgrid(x, y)
dx = np.diff(x)[0]
dy = np.diff(y)[0]
ds = np.sqrt(dx**2 + dy**2)
patches = []
for i in x:
for n, j in enumerate(y):
if n%2:
polygon = mpatches.RegularPolygon([i-dx/2., j], 6, 0.6*dx)
else:
polygon = mpatches.RegularPolygon([i, j], 6, 0.6*dx)
patches.append(polygon)
collection = PatchCollection(patches, cmap=cmap, norm=norm, alpha=1.0)
fig, ax = plt.subplots(1,1)
ax.add_collection(collection)
collection.set_array(example_data.ravel())
plt.show()
which looks like this,
Previous solution, it doesn't tessellate nicely and the hexagons are poorly shaped but you could use a scatter plot with coloured hexagons,
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
nx = 40
ny = 44
example_data = np.random.randint(4, size=(nx,ny))
cmap = colors.ListedColormap(['black', 'green', 'red', 'blue'])
bounds = [0,1,2,3,4]
norm = colors.BoundaryNorm(bounds, cmap.N)
x = np.linspace(0, 1, nx)
y = np.linspace(0, 1, ny)
X, Y = np.meshgrid(x, y)
img = plt.scatter(X.ravel(),Y.ravel(),c=example_data.ravel(), cmap=cmap, norm=norm, s=360, marker=(6, 0), alpha=0.4)
plt.colorbar(img)
plt.show()
which looks like,

How to format a polar contour plot in matplotlib

I have some sample code to make a polar contour plot:
import numpy as np
import matplotlib.pyplot as plt
azimuths = np.radians(np.linspace(0, 180, 90))
zeniths = np.arange(50, 5050, 50)
r, theta = np.meshgrid(zeniths, azimuths)
values = 90.0+5.0*np.random.random((len(azimuths), len(zeniths)))
fig, ax = plt.subplots(subplot_kw=dict(projection='polar'))
ax.set_theta_zero_location("W")
pp = plt.contourf(theta, r, values, label='tmp')
cbar = plt.colorbar(pp, orientation='vertical')
cbar.ax.set_ylabel('scale label')
plt.show()
which gives me something like:
...but I would like something more like this:
...with space in the middle, and only showing 0 to 180 degrees. Does anyone know of a convenient way to do this?
I'm not sure how convenient this is, but here's a hackable solution (taken from here):
import numpy as np
import mpl_toolkits.axisartist.floating_axes as floating_axes
from matplotlib.projections import PolarAxes
from mpl_toolkits.axisartist.grid_finder import FixedLocator, MaxNLocator, \
DictFormatter
import matplotlib.pyplot as plt
tr = PolarAxes.PolarTransform()
degree_ticks = lambda d: (d*np.pi/180, "%d$^\\circ$"%(360-d))
angle_ticks = map(degree_ticks, np.linspace(180, 360, 5))
grid_locator1 = FixedLocator([v for v, s in angle_ticks])
tick_formatter1 = DictFormatter(dict(angle_ticks))
tick_formatter2 = DictFormatter(dict(zip(np.linspace(1000, 6000, 6),
map(str, np.linspace(0, 5000, 6)))))
grid_locator2 = MaxNLocator(5)
gh = floating_axes.GridHelperCurveLinear(tr,
extremes=(2*np.pi, np.pi, 1000, 6000),
grid_locator1=grid_locator1,
grid_locator2=grid_locator2,
tick_formatter1=tick_formatter1,
tick_formatter2=tick_formatter2)
fig = plt.figure()
ax = floating_axes.FloatingSubplot(fig, 111, grid_helper=gh)
fig.add_subplot(ax)
azimuths = np.radians(np.linspace(180, 360, 90)) # added 180 degrees
zeniths = np.arange(1050, 6050, 50) # added 1000
r, theta = np.meshgrid(zeniths, azimuths)
values = 90.0+5.0*np.random.random((len(azimuths), len(zeniths)))
aux_ax = ax.get_aux_axes(tr)
aux_ax.patch = ax.patch
ax.patch.zorder = 0.9
aux_ax.contourf(theta, r, values) # use aux_ax instead of ax
plt.show()
Note that (in order to get the space near the origin), you'll need to shift all your data points by 1000 in the radius direction and by pi in the theta direction (to get the lower hemisphere).
This yields:

Categories

Resources