I would like to plot say 10 lines in 3D in matplotlib, but without having to use ax.plot(x,y,z) 10 times.
This is the ridiculous code I've come up with b/c I can't envision how the zip and arrays actually work together.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = np.array([0.,3.])
y = np.array([0.,0.])
z = np.array([0.,0.])
u = np.array([0.,3.])
v = np.array([.5,.5])
w = np.array([0.,0.])
a = np.array([0.,3.])
b = np.array([1.,1.])
c = np.array([0.,0.])
e = np.array([0.,3.])
d = np.array([1.5,1.5])
f = np.array([0.,0.])
r = np.array([0.,3.])
s = np.array([2.,2.])
t = np.array([0.,0.])
ax.set_xlabel("x axis")
ax.set_ylabel("y axis")
ax.set_zlabel("z axis")
ax.plot(x,y,z)
ax.plot(a,b,c)
ax.plot(r,s,t)
ax.plot(u,v,w)
ax.plot(e,d,f)
plt.show()
I'm guessing I'll use zip and/or a for loop.
Thanks, and here's the figure.
You could store all your data points in a large data array. This way you can loop over the array and do something like this:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# initialize array with size number of lines
data = np.full((2,3), None)
# fill data array with data points [x,y,z]
data[0] = [[0,3],[0,0],[0,0]]
data[1] = [[0,3],[0.5,0.5],[0,0]]
# etc...
# loop over data array and plot lines
for line in data:
ax.plot(line[0],line[1],line[2])
plt.show()
There are many different ways on how to store your data, you could also skip the initialization step by just creating the array in one take:
data = np.array([[[0,3],[0,0],[0,0]],
[[0,3],[0.5,0.5],[0,0]],
[[0,3],[0.5,0.5],[0,0]],
[...] ])
Or use numpy functions like numpy.concatenate to add new lines to the data array.
Related
I'm trying to plot some lines using LineCollection in a plot. Each of these lines is needed to be mapped to colorbar whose range varies for each lines. I tried as explained here
https://matplotlib.org/stable/gallery/lines_bars_and_markers/multicolored_line.html?highlight=line%20collection
In the end, I want a single colorbar, for let's say three lines, covering all ranges. However, the colorbar is set for the last line values. So I looked here
https://matplotlib.org/stable/gallery/images_contours_and_fields/multi_image.html
But I'm not being successful since I'm quite new to Matplotlib. I paste my code below. I'm just trying to map the value of the lines (also shown on y-axis) in a colorbar for all three lines. Any help is appreciated.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import colors
lineSegments = [np.linspace(0,1,10),
np.linspace(0,5,10),
np.linspace(0,2,10)]
xVec = np.linspace(0,1,10)
fig, ax = plt.subplots()
for i in range(0, len(lineSegments)):
cValue = np.linspace( min(lineSegments[i]), max(lineSegments[i]) )
norm = colors.Normalize(vmin=cValue.min(), vmax=cValue.max() )
Points = np.array([xVec, lineSegments[i]]).T.reshape(-1,1,2)
PointSegments = np.concatenate([Points[:-1],Points[1:]], axis=1)
lc = LineCollection(PointSegments, cmap=plt.get_cmap('jet'),
norm=norm)
#plt.gca().add_collection(lc)
ax.add_collection(lc)
ax.set_xlim( min(xVec), max(xVec) )
ax.set_ylim( np.amin(lineSegments), np.amax(lineSegments) )
lc.set_array(cValue)
fig.colorbar(lc)
def update(changed_lines):
for i in range(0, len(lineSegments)):
if (changed_lines.get_cmap() != lc.get_cmap()
or changed_lines.get_clim() != lc.get_clim()):
lc.set_cmap(changed_lines.get_cmap())
lc.set_clim(changed_lines.get_clim())
for i in range(0, len(lineSegments)):
lc.callbacksSM.connect('changed',update)
plt.show()
I have modified your code. Essentially what you need to do is create a norm instance for the entire dataset and then assign color values to the segments according to the colormap you have with the given norm. You can then pass it to the colorbar accordingly.
As such
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import colors
lineSegments = [np.linspace(0,1,10),
np.linspace(0,5,10),
np.linspace(0,2,10)]
xVec = np.linspace(0,1,10)
fig, ax = plt.subplots()
norm = colors.Normalize(vmin=min([ i.min() for i in lineSegments ]),
vmax=max([i.max() for i in lineSegments]))
cmap = plt.get_cmap('jet')
for i in range(0, len(lineSegments)):
cValue = norm(lineSegments[i])
c = cmap(cValue)
Points = np.array([xVec, lineSegments[i]]).T.reshape(-1,1,2)
PointSegments = np.concatenate([Points[:-1],Points[1:]], axis=1)
lc = LineCollection(PointSegments, cmap=cmap,
norm=norm, colors = c)
#plt.gca().add_collection(lc)
ax.add_collection(lc)
ax.set_xlim( min(xVec), max(xVec) )
ax.set_ylim( np.amin(lineSegments), np.amax(lineSegments) )
# lc.set_array(cValue)
sc = plt.cm.ScalarMappable(norm = norm, cmap = cmap)
fig.colorbar(sc)
def update(changed_lines):
for i in range(0, len(lineSegments)):
if (changed_lines.get_cmap() != lc.get_cmap()
or changed_lines.get_clim() != lc.get_clim()):
lc.set_cmap(changed_lines.get_cmap())
lc.set_clim(changed_lines.get_clim())
for i in range(0, len(lineSegments)):
lc.callbacksSM.connect('changed',update)
plt.show()
So this is my code, it's written a little messy and my result is absolutely ridiculous. I have no idea how to fix it.
Also, the seaborn library does not work on my computer in any way.
.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data=pd.read_csv('Data.csv',encoding="latin1",sep=";",engine="python")
table = data.replace(0, 0.1)
plt.plot(table["RMDM"], table["BSURF"], color="#03012d", marker=".", ls="None", markersize=3, label="")
data['RMDM'] = data['RMDM'].astype(float)
data['BSURF'] = data['BSURF'].astype(float)
fig, ax = plt.subplots()
x=data['BSURF']
y=data['RMDM']
ax.set_yscale('log')
ax.set_xscale('log')
plt.style.use('classic')
plt.xlabel('B_LC')
plt.ylabel('RM/DM')
plt.plot(x,y, 'og')
from scipy.stats import linregress
df = data.loc[(data['RMDM'] >0) & (data['BSURF'] >0)]
stats = linregress(np.log10(df["RMDM"]),np.log10(df["BSURF"]))
m = stats.slope
b = stats.intercept
r = stats.rvalue
x = np.logspace(-1, 5, base=10)
y = (m*x+b)
plt.plot(x, y, c='orange', label="fit")
plt.legend()
#m,c=np.polyfit(x,y,1)
#plt.plot(x,m*x+c)
plt.grid()
plt.show()
lmplot can be used to create a linear line through your data. you correctly used np.log for the linear regression data. keep x in terms of the log.
df['log_col1']=np.log(df['col1'])
sns.lmplot(x='log_col1','y='target', data=df, ci=None)
sns.scatterplot(y='target',x='log_col1',data=df)
plt.show()
i am using Matplotlib to show graph of some information that i get from the users,
i want to show it as:axis x will be by the ID of the users and axis y will be by the Winning time that whey have..
I dont understand how can i put the x axis index as the ID of my users.
my code:
import matplotlib.pyplot as plt
import matplotlib,pylab as pylab
import pandas as pd
import numpy as np
#df = pd.read_csv('Players.csv')
df = pd.read_json('Players.json')
# df.groupby('ID').sum()['Win']
axisx = df.groupby('ID').sum()['Win'].keys()
axisy = df.groupby('ID').sum()['Win'].values
fig = pylab.gcf()
# fig.canvas.set_window_title('4 In A Row Statistic')
# img = plt.imread("Oi.jpeg")
# plt.imshow(img)
fig, ax = plt.subplots()
ax.set_xticklabels(axisx.to_list())
plt.title('Game Statistic',fontsize=20,color='r')
plt.xlabel('ID Players',color='r')
plt.ylabel('Wins',color='r')
x = np.arange(len(axisx))
rects = ax.bar(x, axisy, width=0.1)
plt.show()
use plt.xticks(array_of_id). xticks can set the current tick locations and labels of the x-axis.
I'm looking for anything in python that I can use to do a nested proportional area chart in circles. Preferably something built with (or on top of) matplotlib. Here's an example of what such plot looks like for reference:
A nested circle diagram, where the circle area is proportional to the data could look as follows.
It would take a sorted list or array of data and optionally the respective labels as input and plot a couple of circles.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
def nested_circles(data, labels=None, c=None, ax=None,
cmap=None, norm=None, textkw={}):
ax = ax or plt.gca()
data = np.array(data)
R = np.sqrt(data/data.max())
p = [plt.Circle((0,r), radius=r) for r in R[::-1]]
arr = data[::-1] if c is None else np.array(c[::-1])
col = PatchCollection(p, cmap=cmap, norm=norm, array=arr)
ax.add_collection(col)
ax.axis("off")
ax.set_aspect("equal")
ax.autoscale()
if labels is not None:
kw = dict(color="white", va="center", ha="center")
kw.update(textkw)
ax.text(0, R[0], labels[0], **kw)
for i in range(1, len(R)):
ax.text(0, R[i]+R[i-1], labels[i], **kw)
return col
Usage might look like
data = [1,3,4,5,6]
labels = list("ABCDE")
nested_circles(data, labels=labels, cmap="copper", textkw=dict(fontsize=14))
plt.show()
If you want a different colorcoding, take the c argument and supply another list of values, e.g.
data = [1,3,4,5,6]
labels = list("ABCDE")
codes = [5,3,1,4,2]
circles = nested_circles(data, labels=labels, c=codes, cmap="plasma",
textkw=dict(color="black", fontsize=14))
plt.colorbar(circles, label="Codes")
plt.title("Diagram")
plt.show()
I'm using the matplotlib-venn packages for drawing venn diagrams in python. This packages works nicely for drawing Venn diagrams with two or three sets. However, when one of the sets is much larger than the others, the counts in the smaller circles can get close or overlap. Here's an example.
from collections import Counter
import matplotlib.pyplot as plt
from matplotlib_venn import venn2, venn3
sets = Counter()
sets['01'] = 3000
sets['11'] = 3
sets['10'] = 5
setLabels = ['set1', 'set2']
plt.figure()
ax = plt.gca()
v = venn2(subsets = sets, set_labels = setLabels, ax = ax)
plt.title('Venn Diagram')
plt.show()
What I'm looking to do is move the counts (in this case, 3000, 3, and 5) to a legend with colors matching those in the diagram. Wasn't sure how to do this with matplotlib_venn.
You may replace the labels for the venn diagram with empty strings and instead create a legend from the patches of the venn and the respective counts as follows:
from collections import Counter
import matplotlib.pyplot as plt
from matplotlib_venn import venn2, venn3
sets = Counter()
sets['01'] = 3000
sets['11'] = 3
sets['10'] = 5
setLabels = ['set1', 'set2']
plt.figure()
ax = plt.gca()
v = venn2(subsets = sets, set_labels = setLabels, ax = ax)
h, l = [],[]
for i in sets:
# remove label by setting them to empty string:
v.get_label_by_id(i).set_text("")
# append patch to handles list
h.append(v.get_patch_by_id(i))
# append count to labels list
l.append(sets[i])
#create legend from handles and labels
ax.legend(handles=h, labels=l, title="counts")
plt.title('Venn Diagram')
plt.show()