'how to tackle numpy warnings
i am trying to generate a plot with annotations, the issue is that i have for each x value multiple y values correspond to it, so in order to keep x and y similar in size, i wrote the following:
x = [-2,-1,0,1,2]
y = [(22.8,19.6),(8.9,13.7,14.7),(1.9,-1.8),(-3,-5.9,-13.4),(-5.7,-6.8)]
however, i am constantly getting the follwoing warning:
VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray. _data = np.array(data, dtype=dtype, copy=copy,
my full code:
import matplotlib.pyplot as plt
import numpy as np
x = [-2,-1,0,1,2]
y = [(22.8,19.6),(8.9,13.7,14.7),(1.9,-1.8),(-3,-5.9,-13.4),(-5.7,-6.8)]
custom_annotations = ["K464E", "K472E", "K464", "M155E", "K472", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
plt.scatter(x, y, marker="o")
for i, txt in enumerate(custom_annotations):
plt.annotate(txt, (x[i], y[i]))
plt.savefig("1.png")
Solution 1:[1]
You want to build all x-to-y pairs of your data. Then you can easily fill an array with this data, plot it and annotate it. This means that you have to give your reoccurring x-values multiple times.
import matplotlib.pyplot as plt
import numpy as np
plt.close('all')
# We define the data as a 12 x 2 array
# data[:,0] are the x values
# data[:,1] are the y values
data = np.array([
[-2, 22.8],
[-2, 19.6],
[-1, 8.9],
[-1, 13.7],
[-1, 14.7,],
[ 0, 1.9],
[ 0, -1.8],
[ 1, -3],
[ 1, -5.9],
[ 1, -13.4],
[ 2, -5.7],
[ 2, -6.8],
])
custom_annotations = ["K464E", "K472E", "K464", "M155E", "K472", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
plt.scatter(data[:,0], data[:,1], marker="o")
for i, txt in enumerate(custom_annotations):
plt.annotate(txt, (data[i,0], data[i,1]))
Solution 2:[2]
From what I understand, the np arrays must be declared implicitely by matplotlib in your code.
To solve this and remove the warning, you can just declare x and y as numpy array while making sure that the dtype of y is an object (an object can have a varying size here).
Like this :
x = np.array([-2,-1,0,1,2])
y = np.array(
[(22.8,19.6),(8.9,13.7,14.7),(1.9,-1.8),(-3,-5.9,-13.4),(-5.7,-6.8)],
dtype = object)
Solution 3:[3]
In [196]: x = [-2,-1,0,1,2]
...: y = [(22.8,19.6),(8.9,13.7,14.7),(1.9,-1.8),(-3,-5.9,-13.4),(-5.7,-
...: 6.8)]
...: custom_annotations = ["K464E", "K472E", "K464", "M155E", "K472", "M
...: 155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
matplotlib will make arrays from the inputs.
In [197]: np.array(x)
Out[197]: array([-2, -1, 0, 1, 2])
In [198]: np.array(y)
<ipython-input-198-f87824be910b>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
np.array(y)
Out[198]:
array([(22.8, 19.6), (8.9, 13.7, 14.7), (1.9, -1.8), (-3, -5.9, -13.4),
(-5.7, -6.8)], dtype=object)
In [199]: len(_)
Out[199]: 5
The ragged warning arises when making an array from y. The tuples of y differ in size, so it can't make a 2d array from it.
In [200]: len(custom_annotations)
Out[200]: 12
Looks like y has the same number of elements as the annotations:
In [201]: np.hstack(y)
Out[201]:
array([ 22.8, 19.6, 8.9, 13.7, 14.7, 1.9, -1.8, -3. , -5.9,
-13.4, -5.7, -6.8])
In [202]: len(_)
Out[202]: 12
André may have the correct way of pairing x and y. Here's a way to do that given your current lists
Replicate x values to match the y pattern:
In [204]: lens = [len(i) for i in y]
In [205]: lens
Out[205]: [2, 3, 2, 3, 2]
In [207]: x1 = np.array(x).repeat(lens)
In [208]: x1
Out[208]: array([-2, -2, -1, -1, -1, 0, 0, 1, 1, 1, 2, 2])
In [209]: y1 = np.hstack(y)
In [210]: x1.shape
Out[210]: (12,)
In [211]: y1.shape
Out[211]: (12,)
Now the scatter, with 2 (12,) shape arrays works.
In [212]: plt.scatter(x1,y1)
Out[212]: <matplotlib.collections.PathCollection at 0x7fba38be5b80>
Pay attention to the scatter docs:
Parameters
----------
x, y : float or array-like, shape (n, )
The data positions
With annotations (though there might be something better):
In [214]: plt.scatter(x1, y1, marker="o")
...: for i, text in enumerate(custom_annotations):
...: plt.annotate(text, (x1[i], y1[i]))
alternatively, since:
In [224]: for t,i,j in zip(custom_annotations, x1, y1):
...: plt.annotate(t,(i,j))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | André |
| Solution 2 | Maxime Bonnesoeur |
| Solution 3 |

