I am plotting two lists using matplotlib python library. There are two arrays x and y which look like this when plotted-
Click here for plot (sorry don't have enough reputation to post pictures here)
The code used is this-
import matplotlib.pyplot as plt
plt.plot(x,y,"bo")
plt.fill(x,y,'#99d8cp')
It plots the points then connects the points using a line. But the problem is that it is not connecting the points correctly. Point 0 and 2 on x axis are connected wrongly instead of 1 and 2. Similarly on the other end it connects points 17 to 19, instead of 18 to 19. I also tried plotting simple line graph using-
plt.plot(x,y)
But then too it wrongly connected the points. Would really appreciated if anyone could point me in right direction as to why this is happening and what can be done to resolve it.
Thanks!!
The lines of matplotlib expects that the coordinates are in order, therefore you are connecting your points in a 'strange' way (although exactly like you told matplotlib to do, e.g. from (0,1) to (3,2)). You can fix this by simply sorting the data prior to plotting.
#! /usr/bin/env python
import matplotlib.pyplot as plt
x = [20, 21, 22, 23, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 17, 16, 19, 18]
y = [ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1]
x2,y2 = zip(*sorted(zip(x,y),key=lambda x: x[0]))
plt.plot(x2,y2)
plt.show()
That should give you what you want, as shown below:
Related
I'm a learner of vtk, I want to use vtkpolyhedron object to describe an irregular polyhedron, then write it into .vtu file. It has an error when I write it into unstructured grid. I use a cube as example, here is my code
# create a cube polyhedron
polyhedron = vtkPolyhedron()
for i in range(8):
polyhedron.GetPointIds().InsertNextId(i)
polyhedron.Initialize()
polyhedron.GetPoints().InsertNextPoint(0, 0, 0)
polyhedron.GetPoints().InsertNextPoint(1, 0, 0)
polyhedron.GetPoints().InsertNextPoint(1, 1, 0)
polyhedron.GetPoints().InsertNextPoint(0, 1, 0)
polyhedron.GetPoints().InsertNextPoint(0, 0, 1)
polyhedron.GetPoints().InsertNextPoint(1, 0, 1)
polyhedron.GetPoints().InsertNextPoint(1, 1, 1)
polyhedron.GetPoints().InsertNextPoint(0, 1, 1)
face_1 = [6,
4, 0, 3, 2, 1,
4, 0, 4, 7, 3,
4, 4, 5, 6, 7,
4, 5, 1, 2, 6,
4, 0, 1, 5, 4,
4, 2, 3, 7, 6]
polyhedron.SetFaces(face_1)
# write into unstructured grid
polyGrid = vtkUnstructuredGrid()
polyGrid.InsertNextCell(polyhedron.GetCellType(), polyhedron.GetFaces())
The error is
Traceback (most recent call last):
File "D:/science/NMM/python-NMM/script/3D_script/vtk_study/011_convert_unstructured_grid_to_polydata.py", line 145, in <module>
polyGrid.InsertNextCell(polyhedron.GetCellType(), polyhedron.GetFaces())
TypeError: InsertNextCell argument %Id: %V
Then I try to print the polyhedron.getfaces
print(polyhedron.GetFaces())
print(type(polyhedron.GetFaces()))
I get
_0000013b5aca1e00_p_void
<class 'str'>
The document of vtkpolyhedron show it should return a vtkIdList https://vtk.org/doc/nightly/html/classvtkPolyhedron.html#a070ddbec07089276d5f4286b975c830d
Is there any error in the use process?
Thank you very much!
You should call Initialize after SetFaces (at least before further access to the cell)
See this similar example
In found from this doc
Edit
As GetFaces does not seem to work as expected in python I advise to create your data following the pattern of this other example:
create a vtkPoints, add it to the vtkUnstructuredGrid
create a vtkIdList to list the point ids for each face
Add the polyhedron cell to the grid: ugrid.InsertNextCell(VTK_POLYHEDRON, cellIdList)
So from the database, I'm trying to plot a histogram using the matplot lib library in python.
as shown here:
cnx = sqlite3.connect('practice.db')
sql = pd.read_sql_query('''
SELECT CAST((deliverydistance/1)as int)*1 as bin, count(*)
FROM orders
group by 1
order by 1;
''',cnx)
which outputs
This
From the sql table, I try to extract the columns using a for loop and place them in array.
distance =[]
counts = []
for x,y in sql.iterrows():
y = y["count(*)"]
counts.append(y)
distance.append(x)
print(distance)
print(counts)
OUTPUT:
distance = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
counts = [57136, 4711, 6569, 7268, 6755, 5757, 7643, 6175, 7954, 9418, 4945, 4178, 2844, 2104, 1829, 9, 4, 1, 3]
When I plot a histogram
plt.hist(counts,bins=distance)
I get this out put:
click here
My question is, how do I make it so that the count is on the Y axis and the distance is on the X axis? It doesn't seem to allow me to put it there.
you could also skip the for loop and plot direct from your pandas dataframe using
sql.bin.plot(kind='hist', weights=sql['count(*)'])
or with the for loop
import matplotlib.pyplot as plt
import pandas as pd
distance =[]
counts = []
for x,y in sql.iterrows():
y = y["count(*)"]
counts.append(y)
distance.append(x)
plt.hist(distance, bins=distance, weights=counts)
You can skip the middle section where you count the instances of each distance. Check out this example:
import pandas as pd
import numpy as np
df = pd.DataFrame({'distance':np.round(20 * np.random.random(100))})
df['distance'].hist(bins = np.arange(0,21,1))
Pandas has a built-in histogram plot which counts, then plots the occurences of each distance. You can specify the bins (in this case 0-20 with a width of 1).
If you are not looking for a bar chart and are looking for a horizontal histogram, then you are looking to pass orientation='horizontal':
distance = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
# plt.style.use('dark_background')
counts = [57136, 4711, 6569, 7268, 6755, 5757, 7643, 6175, 7954, 9418, 4945, 4178, 2844, 2104, 1829, 9, 4, 1, 3]
plt.hist(counts,bins=distance, orientation='horizontal')
Use :
plt.bar(distance,counts)
Trying to understand how the time series of matplotlib works.
Unfortunately, this doc just load data straight from a file using bumpy, which makes it very cryptic for non-fluent numpy adepts.
From the doc:
with cbook.get_sample_data('goog.npz') as datafile:
r = np.load(datafile)['price_data'].view(np.recarray)
r = r[-30:] # get the last 30 days
# Matplotlib works better with datetime.datetime than np.datetime64, but the
# latter is more portable.
date = r.date.astype('O')
In my case, I have a dictionary of datetime (key) and int, which I can transform to an array or list, but I wasn't quite successful to get anything that pyplot would take and the doc isn't much of help, especially for timeseries.
def toArray(dict):
data = list(dict.items())
return np.array(data)
>>>
[datetime.datetime(2020, 5, 4, 16, 44) -13]
[datetime.datetime(2020, 5, 4, 16, 45) 7]
[datetime.datetime(2020, 5, 4, 16, 46) -11]
[datetime.datetime(2020, 5, 4, 16, 47) -75]
[datetime.datetime(2020, 5, 4, 16, 48) -41]
[datetime.datetime(2020, 5, 4, 16, 49) -39]
[datetime.datetime(2020, 5, 4, 16, 50) -4]
The most important part is to split X axis from Y axis (in your case - dates from values). Using your function toArray() to retrieve data, the following code produces a desired result:
import matplotlib.pyplot as plt
data = toArray(your_dict)
fig, ax = plt.subplots(figsize=(20, 10))
dates = [x[0] for x in data]
values = [x[1] for x in data]
ax.plot(dates, values, 'o-')
ax.set_title("Default")
fig.autofmt_xdate()
plt.show()
Note how we split data from 2D array of dates and values into two 1D arrays dates and values.
I would like to annotate some points in a matplotlib plot (dynamically ofc) with "arc" connectionstyles in such a way that the annotations are grouped at the top, the connectors running to their respective x-positions, but stop at a defined y-position, and extend as straight arms from their to the data point (see fig). The solution might be manipulating the individual "armB"-values, but the problem there is that those are only in points and don't correspond to the data coordinate system. The reason I don't just use straight lines in the first place is that in the real data, the points are sometimes too close together and the text would overlap, hence the bent "arrows". Oh, and it should dynamically adapt to the zoom level (the final plot being interactive), but I think I'll be able to pull that off once the connection line problem is solved. Minimal working example:
import matplotlib.pyplot as plt
x=[2, 3, 4, 6, 7, 8, 10, 11]
y=[1, 3, 4, 2, 3, 1, 5, 2,]
tx=[3, 4, 5, 6, 7, 8, 9, 10]
yd=dict(zip(x, y))
plt.scatter(x, y)
plt.xlim(0, 14)
plt.ylim(0, 7)
arpr = {"arrowstyle": "-", "connectionstyle": "arc,angleA=-90,armA=20,angleB=90,armB=20,rad=10"}
for i, j in zip(x, tx):
#lines all the way down but messy
plt.annotate("foo", (i, yd[i]), (j, 6), arrowprops=arpr, rotation="vertical")
#lines orderly, but incomplete
plt.annotate("foo", (i, 5), (j, 6), arrowprops=arpr, rotation="vertical")
What I would like (red lines are the issue, added in the pic w/ MS paint...):
Just clipping the connectors to the data points, not good:
You can set the length of armB so that it's dependent on the position of the point.
Here's an example for what I thought looked good:
connection = "arc,angleA=-90,armA=20,angleB=90,rad=10,"
arpr = {"arrowstyle": "-"}
for i, j in zip(x, tx):
#lines all the way down but messy
arpr["connectionstyle"] = connection + "armB="+ "{0}".format((5-yd[i])*30)
plt.annotate("foo", (i, yd[i]), (j, 6), arrowprops=arpr, rotation="vertical")
I have an array of the shape (6416,17,3). I am trying to plot each entry (17,3) after each other in a 3D grid as if it's a video. This is the code I wrote for the visualizer function:
def draw_limbs_3d(ax, joints_3d, limb_parents):
# ax.clear()
for i in range(joints_3d.shape[0]):
x_pair = [joints_3d[i, 0], joints_3d[limb_parents[i], 0]]
y_pair = [joints_3d[i, 1], joints_3d[limb_parents[i], 1]]
z_pair = [joints_3d[i, 2], joints_3d[limb_parents[i], 2]]
ax.plot(x_pair, y_pair, zs=z_pair, linewidth=3)
def visualizer(joints_3d):
joint_parents = [16, 15, 1, 2, 3, 1, 5, 6, 14, 8, 9, 14, 11, 12, 14, 14, 1]
fig = plt.figure('3D Pose')
ax_3d = plt.axes(projection='3d')
plt.ion()
ax_3d.clear()
ax_3d.clear()
ax_3d.view_init(-90, -90)
ax_3d.set_xlim(-1000, 1000)
ax_3d.set_ylim(-1000, 1000)
ax_3d.set_zlim(0, 4000)
ax_3d.set_xticks([])
ax_3d.set_yticks([])
ax_3d.set_zticks([])
white = (1.0, 1.0, 1.0, 0.0)
ax_3d.w_xaxis.set_pane_color(white)
ax_3d.w_yaxis.set_pane_color(white)
ax_3d.w_xaxis.line.set_color(white)
ax_3d.w_yaxis.line.set_color(white)
ax_3d.w_zaxis.line.set_color(white)
draw_limbs_3d(ax_3d, joints_3d, joint_parents)
and I use this code to run on all entries:
joints_3d = np.load('output.npy')
for joint in joints_3d:
joint = joint.reshape((17,3))
visualizer(joint)
which causes the program to crash. It works for one array though and I get the correct plot. I would be grateful if you could help me. Thank you.