numpy ndarray object has no attribute append - python

I am struggling with a program I am making on the part where I have to store values that I get from my loop in an array.
What I tried to do is to make an empty array called M. Then for every new value "a" calculated in a loop I use the command M.append(a) to add the value a to the array M.
The thing is, python says this error : 'numpy.ndarray' object has no attribute 'append'
and I don't know how to fix it.
Here is my code :
import numpy as np
from matplotlib import pyplot as plt
with open('expFcn0.txt') as f:
M = np.array([])
print(M)
lines = f.readlines()
x = [float(line.split()[0]) for line in lines]
y = [float(line.split()[1]) for line in lines]
for i in range(0,181):
a=np.log(y[i])/x[i]
print(a)
i=i+1
M.append(a)
print(M)
plt.plot(x, y, 'r--')
plt.xlabel('Time')
plt.ylabel('Biomass')
plt.title('Exponential Function')
plt.show()
Thank you very much!

Numpy arrays don't have a method append(). You need to use np.append(array, values) as per the documentation, or for your case, np.append(M, a).

Other answers explain that numpy arrays do not have an .append() method and point to numpy.append. Using numpy.append, however, is bad practice because it creates a new array each time. A better solution is to create one numpy and fill it during the for loop (see end of answer).
An even better solution would make use of numpy's broadcasting. That's a core feature of numpy, and it's what helps make numpy fast.
import numpy as np
with open('expFcn0.txt') as f:
lines = f.readlines()
x = np.array([float(line.split()[0]) for line in lines])
y = np.array([float(line.split()[1]) for line in lines])
M = np.log(y) / x
You can also look into numpy.loadtxt to read the file into a numpy array directly.
How to fill a numpy array in a for loop:
import numpy as np
with open('expFcn0.txt') as f:
lines = f.readlines()
x = [float(line.split()[0]) for line in lines]
y = [float(line.split()[1]) for line in lines]
M = np.zeros(181)
for i in range(181):
a = np.log(y[i])/x[i]
print(a)
M[i] = a

Numpy arrays do not have an append method. Use the Numpy append function instead:
M = np.append(M, a)

Related

Zipping coordinates and then accessing them

I have a three vectors of x,y,z coordinates, something like
x = [1,2,3,4,5]
y = [6,7,8,9,10]
z = [11,12,13,14,15]
I want to zip them to have an 5x3 array of coordinates. But when I do
coords = zip(x,y,z)
and then try to print coords, I get
and I cannot plot them either,
How can I get 5x3 array?
You can use numpy function directly:
np.array(list(zip(x,y,z)))
If you didn't import numpy:
import numpy as np
call list on the zip object or use it in a list comprehension.

Plot 3rd axis of a 3D numpy array

I have a 3D numpy array that is a stack of 2D (m,n) images at certain timestamps, t. So my array is of shape (t, m, n). I want to plot the value of one of the pixels as a function of time.
e.g.:
import numpy as np
import matplotlib.pyplot as plt
data_cube = []
for i in xrange(10):
a = np.random(100,100)
data_cube.append(a)
So my (t, m, n) now has shape (10,100,100). Say I wanted a 1D plot the value of index [12][12] at each of the 10 steps I would do:
plt.plot(data_cube[:][12][12])
plt.show()
But I'm getting index out of range errors. I thought I might have my indices mixed up, but every plot I generate seems to be in the 'wrong' axis, i.e. across one of the 2D arrays, but instead I want it 'through' the vertical stack. Thanks in advance!
Here is the solution: Since you are already using numpy, convert you final list to an array and just use slicing. The problem in your case was two-fold:
First: Your final data_cube was not an array. For a list, you will have to iterate over the values
Second: Slicing was incorrect.
import numpy as np
import matplotlib.pyplot as plt
data_cube = []
for i in range(10):
a = np.random.rand(100,100)
data_cube.append(a)
data_cube = np.array(data_cube) # Added this step
plt.plot(data_cube[:,12,12]) # Modified the slicing
Output
A less verbose version that avoids iteration:
data_cube = np.random.rand(10, 100,100)
plt.plot(data_cube[:,12,12])

Newton method in python for multivariables (system of equations)

My code is running fine for first iteration but after that it outputs the following error:
ValueError: matrix must be 2-dimensional
To the best of my knowledge (which is not much in python), my code is correct. but I don't know, why it is not running correctly for all given iterations. Could anyone help me in this problem.
from __future__ import division
import numpy as np
import math
import matplotlib.pylab as plt
import sympy as sp
from numpy.linalg import inv
#initial guesses
x = -2
y = -2.5
i1 = 0
while i1<5:
F= np.matrix([[(x**2)+(x*y**3)-9],[(3*y*x**2)-(y**3)-4]])
theta = np.sum(F)
J = np.matrix([[(2*x)+y**3, 3*x*y**2],[6*x*y, (3*x**2)-(3*y**2)]])
Jinv = inv(J)
xn = np.array([[x],[y]])
xn_1 = xn - (Jinv*F)
x = xn_1[0]
y = xn_1[1]
#~ print theta
print xn
i1 = i1+1
I believe xn_1 is a 2D matrix. Try printing it you and you will see [[something], [something]]
Therefore to get the x and y, you need to use multidimensional indexing. Here is what I did
x = xn_1[0,0]
y = xn_1[1,0]
This works because within the 2D matrix xn_1 are two single element arrays. Therefore we need to further index 0 to get that single element.
Edit: To clarify, xn_1[1,0] means to index 1 and then take that subarray and index 0 on that. And although according to Scipy it may seem that it should be functionally equivalent to xn_1[1][0], that only applies to the general np.array type and not the np.matrix type. Here is an excellent thread on SO that explains this.
So you should use the xn_1[1,0] way to get the element you want.
xn_1 is a numpy matrix, so it's elements are accessed with the item() method, not like an array. (with []s)
So just change
x = xn_1[0]
y = xn_1[1]
to
x = xn_1.item(0)
y = xn_1.item(1)

Plotting a heat map from three lists: X, Y, Intensity

I don't get how to create a heatmap (or contour plot) when I have x, y, intensity. I have a file which looks like this:
0,1,6
0,2,10
....
So far:
with open('eye_.txt', 'r') as f:
for line in f:
for word in line.split():
l = word.strip().split(',')
x.append(l[0])
y.append(l[1])
z.append(l[2])
Tried using pcolormesh but it wants a shape object and I'm unsure how to convert these lists into a NumPy array.
I tried:
i,j = np.meshgrid(x,y)
arr = np.array(z)
plt.pcolormesh(i,j,arr)
plt.show()
It tells me that:
IndexError: too many indices
Can someone stop me from bashing my head against a keyboard, please?
OK, there's a few steps to this.
First, a much simpler way to read your data file is with numpy.genfromtxt. You can set the delimiter to be a comma with the delimiter argument.
Next, we want to make a 2D mesh of x and y, so we need to just store the unique values from those to arrays to feed to numpy.meshgrid.
Finally, we can use the length of those two arrays to reshape our z array.
(NOTE: This method assumes you have a regular grid, with an x, y and z for every point on the grid).
For example:
import matplotlib.pyplot as plt
import numpy as np
data = np.genfromtxt('eye_.txt',delimiter=',')
x=data[:,0]
y=data[:,1]
z=data[:,2]
## Equivalently, we could do that all in one line with:
# x,y,z = np.genfromtxt('eye_.txt', delimiter=',', usecols=(0,1,2))
x=np.unique(x)
y=np.unique(y)
X,Y = np.meshgrid(x,y)
Z=z.reshape(len(y),len(x))
plt.pcolormesh(X,Y,Z)
plt.show()
In case you don't have a regular grid (i.e. a value of z for each meshgrid value of x and y), you can use a more general method based on pandas data frames:
import pandas as pd
import seaborn as sns
import matplotlib.pypot as plt
data = pd.DataFrame(data={'x':x, 'y':y, 'z':z})
data = data.pivot(index='x', columns='y', values='z')
sns.heatmap(data)
plt.show()
The pivot method will use unique values from index and columns to construct a table with missing measurments set to NaN. The table can then be plotted as a heatmap.
The index error arises from the fact that pcolormesh expects a 2D array while your arr is a 1D vector. Also if I understand correctly, your input file has the form
0,1,z
0,2,z
...
0,ymax,z
...
1,1,z
1,2,z
...
xmax,ymax,z
In that case meshgrid(x,y) will not work as it expects something like meshgrid(range(xmax),range(ymax)) i.e. vectors without repeated values.
In your case you need to find out how many distinct x and y values there are and then simply reshape your vectors into 2D arrays.
shape = np.unique(x).shape[0],np.unique(y).shape[0]
x_arr = x.reshape(shape)
y_arr = y.reshape(shape)
z_arr = z.reshape(shape)
plt.pcolormesh(x_arr,y_arr,z_arr)
To convert a list into a numpy array you can use np.asarray.
Here's an easy way to get a heatmap, you should be able to adapt this example to your problem.
import matplotlib.pyplot as plt
import numpy as np
a = [[1,2,3], [3,4,5], [5,6,7], [7, 8, 9]]
b = np.asarray(a)
plt.pcolor(b)
plt.show()
To read the data in like a list of lists you can do:
a = []
for line in file.readlines():
a.append( map( int, line.split(',') ) )
in short. In a longer version it's the equivalent of:
a = []
for line in file.readlines():
tmp = line.split(',')
inttmp = [int(x) for x in a]
a.append(inttmp)

How do I create a numpy array using a function?

I am using np.fromfunction to create an array of a specific sized based on a function. It looks like this:
import numpy as np
test = [[1,0],[0,2]]
f = lambda i, j: sum(test[i])
matrix = np.fromfunction(f, (len(test), len(test)), dtype=int)
However, I receive the following error:
TypeError: only integer arrays with one element can be converted to an index
The function needs to handle numpy arrays. An easy way to get this working is:
import numpy as np
test = [[1,0],[0,2]]
f = lambda i, j: sum(test[i])
matrix = np.fromfunction(np.vectorize(f), (len(test), len(test)), dtype=int)
np.vectorize returns a vectorized version of f, which will handle the arrays correctly.

Categories