How to make a 4d plot using Python with matplotlib - python

I am looking for a way to create four-dimensional plots (surface plus a color scale) using Python and matplotlib. I am able to generate the surface using the first three variables, but I am not having success adding the color scale for the fourth variable. Here is a small subset of my data below. Any help would be greatly appreciated. Thanks
Data Subset
var1 var2 var3 var4
10.39 73.32 2.02 28.26
11.13 68.71 1.86 27.83
12.71 74.27 1.89 28.26
11.46 91.06 1.63 28.26
11.72 85.38 1.51 28.26
13.39 78.68 1.89 28.26
13.02 68.02 2.01 28.26
12.08 64.37 2.18 28.26
11.58 60.71 2.28 28.26
8.94 65.67 1.92 27.04
11.61 59.57 2.32 27.52
19.06 74.49 1.69 63.35
17.52 73.62 1.73 63.51
19.52 71.52 1.79 63.51
18.76 67.55 1.86 63.51
19.84 53.34 2.3 63.51
20.19 59.82 1.97 63.51
17.43 57.89 2.05 63.38
17.9 59.95 1.89 63.51
18.97 57.84 2 63.51
19.22 57.74 2.05 63.51
17.55 55.66 1.99 63.51
19.22 101.31 6.76 94.29
19.41 99.47 6.07 94.15
18.99 94.01 7.32 94.08
19.88 103.57 6.98 94.58
19.08 95.38 5.66 94.14
20.36 100.43 6.13 94.47
20.13 98.78 7.37 94.47
20.36 89.36 8.79 94.71
20.96 84.48 8.33 94.01
21.02 83.97 6.78 94.72
19.6 95.64 6.56 94.57

To create the plot you want, we need to use matplotlib's plot_surface to plot Z vs (X,Y) surface, and then use the keyword argument facecolors to pass in a new color for each patch.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# create some fake data
x = y = np.arange(-4.0, 4.0, 0.02)
# here are the x,y and respective z values
X, Y = np.meshgrid(x, y)
Z = np.sinc(np.sqrt(X*X+Y*Y))
# this is the value to use for the color
V = np.sin(Y)
# create the figure, add a 3d axis, set the viewing angle
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.view_init(45,60)
# here we create the surface plot, but pass V through a colormap
# to create a different color for each patch
ax.plot_surface(X, Y, Z, facecolors=cm.Oranges(V))

Related

Obtaining 2 or more coefficients from defined equation using regression methods

I'm looking to run this code that enables to solve for the x number of unknowns (c_10, c_01, c_11 etc.) just from plotting the graph.
Some background on the equation:
Mooney-Rivlin model (1940) with P1 = c_10[(2*λ+λ**2)-3]+c_01[(λ**-2+2*λ)-3].
P1 (or known as P) and lambda are data pre-defined in numerical terms in the table below (sheet ExperimentData of experimental_data1.xlsx):
λ P
1.00 0.00
1.01 0.03
1.12 0.14
1.24 0.23
1.39 0.32
1.61 0.41
1.89 0.50
2.17 0.58
2.42 0.67
3.01 0.85
3.58 1.04
4.03 1.21
4.76 1.58
5.36 1.94
5.76 2.29
6.16 2.67
6.40 3.02
6.62 3.39
6.87 3.75
7.05 4.12
7.16 4.47
7.27 4.85
7.43 5.21
7.50 5.57
7.61 6.30
I have tried obtaining coefficients using Linear regression. However, to my knowledge, random forest is not able to obtain multiple coefficients using
reg.coef_
Tried SVR with
reg.dual_coef_
However keeps obtaining error
ValueError: not enough values to unpack (expected 2, got 1)
Code below:
data = pd.read_excel('experimental_data.xlsx', sheet_name='ExperimentData')
X_s = [[(2*λ+λ**2)-3, (λ**-2+2*λ)-3] for λ in data['λ']]
y_s = data['P']
svr = SVR()
svr.fit(X_s, y_s)
c_01, c_10 = svr.dual_coef_
And for future proofing this method, if lets say there are more than 2 coefficients, are there other methods apart from Linear Regression?
For example, referring to Ishihara model (1951) where
P1 = {2*c_10 + 4*c_20*c_01[(2*λ**-1+λ**2) - 3]*[(λ**-2 + 2*λ) - 3] + c_20 * c_01 * (λ**-1) * [(2*λ**-1 + λ**2) - 3]**2}*{λ - λ**-2}
Any comments is greatly appreciated!

I'm getting float axis even with the command MaxNlocator(integer=True)

I have this df called normales:
CODIGO MES TMAX TMIN PP
0 000130 Enero 31.3 23.5 51.1
1 000130 Febrero 31.7 23.8 136.7
2 000130 Marzo 31.8 23.9 119.5
3 000130 Abril 31.5 23.7 55.6
4 000130 Mayo 30.6 23.1 15.6
... ... ... ... ...
4447 158328 Agosto 11.9 -10.6 2.2
4448 158328 Septiembre 13.2 -9.1 1.2
4449 158328 Octubre 14.6 -8.2 4.9
4450 158328 Noviembre 15.4 -7.2 11.1
4451 158328 Diciembre 14.7 -5.3 35.9
With this code i'm plotting time series and bars:
from matplotlib.ticker import MaxNLocator
from matplotlib.font_manager import FontProperties
for code, data in normales.groupby('CODIGO'):
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, sharex=False, sharey=False,figsize=(20, 15))
data.plot('MES',["TMAX"], alpha=0.5, color='red', marker='P', fontsize = 15.0,ax=ax1)
data.plot('MES',["TMIN"], alpha=0.5,color='blue',marker='D', fontsize = 15.0,ax=ax2)
data.plot('MES',["PP"],kind='bar',color='green', fontsize = 15.0,ax=ax3)
tabla=ax4.table(cellText=data[['TMAX','TMIN','PP']].T.values,colLabels=["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto",
"Septiembre","Octubre","Noviembre","Diciembre"],
rowLabels=data[['TMAX','TMIN','PP']].columns,rowColours =["red","blue","green"],
colColours =["black"] * 12,loc="center",bbox = [0.0, -0.5, 1, 1])
tabla.auto_set_font_size(False)
tabla.set_fontsize(15)
tabla.scale(1,2)
ax4.axis('off')
ax1.set_ylabel("Temperatura\nMáxima °C/mes", fontsize = 15.0)
ax1.yaxis.set_major_locator(MaxNLocator(integer=True))
ax2.set_ylabel("Temperatura\nMínima °C/mes", fontsize = 15.0)
ax2.yaxis.set_major_locator(MaxNLocator(integer=True))
ax3.set_ylabel("Precipitación mm/mes", fontsize = 15.0)
ax3.yaxis.set_major_locator(MaxNLocator(integer=True))
ax1.set_xlabel("")
ax2.set_xlabel("")
ax3.set_xlabel("")
ax4.set_xlabel("")
You can realize that i'm using ax.yaxis.set_major_locator(MaxNLocator(integer=True)) in every axis to make integer the numbers of the axis. Although i'm using ax.yaxis.set_major_locator(MaxNLocator(integer=True)) i'm getting graphics with non integer (float) values in the yaxis. Do you know why this is happening?
Thanks in advance.
From the MaxNLocator docs:
integer bool, default: False
If True, ticks will take only integer values, provided at least min_n_ticks integers are found within the view limits.
....
min_n_ticks int, default: 2
You need to change min_n_ticks to 1 since ax2 only has one integer within the view limits, namely 12.

Plot bar and line using both right and left axis in Matplotlib

Give a dataframe as follows:
date gdp tertiary_industry gdp_growth tertiary_industry_growth
0 2015/3/31 3768 2508 10.3 11.3
1 2015/6/30 8285 5483 10.9 12.0
2 2015/9/30 12983 8586 11.5 12.7
3 2015/12/31 18100 12086 10.5 13.2
4 2016/3/31 4118 2813 13.5 14.6
5 2016/6/30 8844 6020 13.3 14.3
6 2016/9/30 14038 9513 14.4 13.9
7 2016/12/31 19547 13557 16.3 13.3
8 2017/3/31 4692 3285 13.3 12.4
9 2017/6/30 9891 6881 12.9 12.5
10 2017/9/30 15509 10689 12.7 12.3
11 2017/12/31 21503 15254 14.8 12.7
12 2018/3/31 4954 3499 12.4 11.3
13 2018/6/30 10653 7520 12.9 12.4
14 2018/9/30 16708 11697 13.5 13.0
15 2018/12/31 22859 16402 14.0 13.2
16 2019/3/31 5508 3983 13.5 13.9
17 2019/6/30 11756 8556 10.2 13.4
18 2019/9/30 17869 12765 10.2 14.8
19 2019/12/31 23629 16923 11.6 15.2
20 2020/3/31 5229 3968 11.9 14.9
I have applied following code to draw a bar plot for gdp and tertiary_industry.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib.ticker as ticker
import matplotlib.style as style
style.available
style.use('fivethirtyeight')
from pylab import rcParams
plt.rcParams["figure.figsize"] = (20, 10)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
import matplotlib
matplotlib.matplotlib_fname()
plt.rcParams.update({'font.size': 25})
colors = ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3']
df = df.sort_values(by = 'date')
df['date'] = pd.to_datetime(df['date']).dt.to_period('M')
df = df.set_index('date')
df.columns
cols = ['gdp', 'tertiary_industry']
df[cols] = df[cols].apply(pd.to_numeric, errors='coerce')
color_dict = dict(zip(cols, colors))
plt.figure(figsize=(20, 10))
df[cols].plot(color=[color_dict.get(x, '#333333') for x in df.columns], kind='bar', width=0.8)
plt.xticks(rotation=45)
plt.xlabel("")
plt.ylabel("million dollar")
fig = plt.gcf()
plt.show()
plt.draw()
fig.savefig("./gdp.png", dpi=100, bbox_inches = 'tight')
plt.clf()
The output from the code above:
Now I want to use line type and right axis to draw gdp_growth and tertiary_industry_growth, which are percentage values, on the same plot.
Please note I want to use colors from customized color list in the code instead of default ones.
How could I do that based on code above? Thanks a lot for your kind help.
This is what I would do:
#convert to datetime
df['date'] = pd.to_datetime(df['date']).dt.to_period('M')
cols = ['gdp', 'tertiary_industry']
colors = ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3']
df[cols] = df[cols].apply(pd.to_numeric, errors='coerce')
# modify color_dict here:
color_dict = dict(zip(cols, colors))
# initialize an axis instance
fig, ax = plt.subplots(figsize=(10,6))
# plot on new instance
df.plot.bar(y=cols,ax=ax,
color=[color_dict.get(x, '#333333') for x in cols])
# create a twinx axis
ax1 = ax.twinx()
# plot the other two columns on this axis
df.plot.line(y=['gdp_growth','tertiary_industry_growth'], ax=ax1,
color=[color_dict.get(x, '#333333') for x in line_cols])
ax.set_xticklabels(df['date'])
# set y-axes labels:
ax.set_ylabel('Million Dollar')
ax1.set_ylabel('%')
# set x-axis label
ax.set_xlabel('Quarter')
plt.show()
Output:
If you replace both colors=[...] in the above codes with your original color=[color_dict.get(x, '#333333') for x in df.columns] you would get

Calculating Rolling Mean of Temperature Anomalies- python

The data set is indexed by year-month-day (dates) and has columns TMAX and TMIN.
I need to calculate rolling means of each of the anomalies you calculated. Use a window of 10 years and have the window centered, then add this to your plot.
This part of the code creates a plot of anomalies:
tmaxanom = cll.TMAX - cll.TMAX.mean()
tminanom = cll.TMIN - cll.TMIN.mean()
yearlytmax = tmaxanom.resample('1y').mean()
yearlytmin = tminanom.resample('1y').mean()
ax = plt.plot(yearlytmax, color='red', lw=2, ms=3, marker='o')
ax = plt.plot(yearlytmin, color='blue', lw=2, ms=3, marker='o')
plt.legend(('TMAX Anomaly', 'TMIN Anomaly'), loc='best')
plt.xlabel("Year")
plt.ylabel("Degrees C")
plt.title("Temperature Anomalies in College Station, Texas")
I am trying to calculate rolling means by the following:
rolmean = yearlytmax.rolling(window=10, center=True)
rolmean2 = yearlytmin.rolling(window=10, center=True)
plt.plot(rolmean, color='pink', label='Rolling Mean Max')
plt.plot(rolmean2, color='yellow', label='Rolling Mean Min')
However this is causing python to throw an error: NotImplementedError: See issue #11704 https://github.com/pandas-dev/pandas/issues/11704
I followed the link, however am still unsure how to fix this problem.
A Sample of data is:
DATE TMAX. TMIN
1951-08-01 37.8 22.8
1951-08-02 37.8 22.2
1951-08-03 40.0 23.9
1951-08-04 41.7 26.7
1951-08-05 41.1 26.1
1951-08-06 40.6 26.7
1951-08-07 38.9 24.4
1951-08-08 39.4 25.0
1951-08-09 38.9 24.4
1951-08-10 38.9 24.4
1951-08-11 38.9 22.2
1951-08-12 40.0 23.3
1951-08-13 40.6 22.8
1951-08-14 41.1 25.6
1951-08-15 41.1 23.9
1951-08-16 42.2 24.4
1951-08-17 41.7 24.4
1951-08-18 36.7 21.7
1951-08-19 31.7 23.3
1951-08-20 36.7 21.7
1951-08-21 38.3 23.3
1951-08-22 39.4 22.2
1951-08-23 37.2 23.9
1951-08-24 37.8 23.3
1951-08-25 38.3 23.9
1951-08-26 37.8 23.3
1951-08-27 37.8 23.9
1951-08-28 38.3 22.8
1951-08-29 38.3 23.3
1951-08-30 38.9 23.9
... ... ...
I got it to work by adding in .mean() to the end of each of the rolling mean commands, so it looks like:
rolmean = yearlytmax.rolling(window=10, center=True).mean()
rolmean2 = yearlytmin.rolling(window=10, center=True).mean()

How to find point of intersection of two line segments in Python? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have data with one independent variable x and two dependent variables y1 and y2 as shown below:
x y1 y2
-1.5 16.25 1.02
-1.25 17 1.03
-1 15 1.03
-0.75 9 1.09
-0.5 5.9 1.15
-0.25 5.2 1.17
0 4.77 1.19
+0.25 3.14 1.35
+0.5 2.5 1.54
+0.75 2.21 1.69
+1 1.91 1.96
+1.25 1.64 2.27
+1.5 1.52 2.56
+1.75 1.37 3.06
+2 1.24 4.12
+2.25 1.2 4.44
+2.5 1.18 4.95
+2.75 1.12 6.49
+3 1.07 10
So, here the value of x where y1 = y2 is somewhere around +1. How do I read the data and calculate this in python?
The naive solution goes like this:
txt = """-1.5 16.25 1.02
-1.25 17 1.03
-1 15 1.03
-0.75 9 1.09
-0.5 5.9 1.15
-0.25 5.2 1.17
0 4.77 1.19
+0.25 3.14 1.35
+0.5 2.5 1.54
+0.75 2.21 1.69
+1 1.91 1.96
+1.25 1.64 2.27
+1.5 1.52 2.56
+1.75 1.37 3.06
+2 1.24 4.12
+2.25 1.2 4.44
+2.5 1.18 4.95
+2.75 1.12 6.49
+3 1.07 10"""
import numpy as np
# StringIO behaves like a file object, use it to simulate reading from a file
from StringIO import StringIO
x,y1,y2=np.transpose(np.loadtxt(StringIO(txt)))
p1 = np.poly1d(np.polyfit(x, y1, 1))
p2 = np.poly1d(np.polyfit(x, y2, 1))
print 'equations: ',p1,p2
#y1 and y2 have to be equal for some x, that you solve for :
# a x+ b = c x + d --> (a-c) x= d- b
a,b=list(p1)
c,d=list(p2)
x=(d-b)/(a-c)
print 'solution x= ',x
output:
equations:
-3.222 x + 7.323
1.409 x + 1.686
solution x= 1.21717324767
But then you plot the 'lines':
import matplotlib.pyplot as p
%matplotlib inline
p.plot(x,y1,'.-')
p.plot(x,y2,'.-')
And you realize you can't use a linear assumption but for a few segments.
x,y1,y2=np.transpose(np.loadtxt(StringIO(txt)))
x,y1,y2=x[8:13],y1[8:13],y2[8:13]
p1 = np.poly1d(np.polyfit(x, y1, 1))
p2 = np.poly1d(np.polyfit(x, y2, 1))
print 'equations: ',p1,p2
a,b=list(p1)
c,d=list(p2)
x0=(d-b)/(a-c)
print 'solution x= ',x0
p.plot(x,y1,'.-')
p.plot(x,y2,'.-')
Output:
equations:
-1.012 x + 2.968
1.048 x + 0.956
solution x= 0.976699029126
Even now one could improve by leaving two more points out (looking very linear, but that can be coincidental for a few points).
x,y1,y2=np.transpose(np.loadtxt(StringIO(txt)))
x1,x2=x[8:12],x[9:13]
y1,y2=y1[8:12],y2[9:13]
p1 = np.poly1d(np.polyfit(x1, y1, 1))
p2 = np.poly1d(np.polyfit(x2, y2, 1))
print 'equations: ',p1,p2
a,b=list(p1)
c,d=list(p2)
x0=(d-b)/(a-c)
print 'solution x= ',x0
import matplotlib.pyplot as p
%matplotlib inline
p.plot(x1,y1,'.-')
p.plot(x2,y2,'.-')
Output:
equations:
-1.152 x + 3.073
1.168 x + 0.806
solution x= 0.977155172414
Possibly better would be to use more points and apply a 2nd order interpolation np.poly1d(np.polyfit(x,y1,2)) and then solve the equality for two 2nd order polynomials, which I leave as an exercise (quadratic equation) for the reader.

Categories

Resources