Importing just one value with numpy.genfromtxt - python

I would like to import just one value from a csv file. So far, I have been succesfull at using the skip_header and skip_footer options to seek out this element. It is a float value. One problem though, when I try to use this one element from my array, I get an error. Example:
import numpy as np
x = np.genfromtxt('junker.txt',skip_header=6,skip_footer=7)
print x
returns
array(10)
however
print x[0]
returns
TypeError: len() of unsized object
I just want to be able to use this value however I cannot because it's in a numpy array. Please help

a numpy array in that form is actually just a number. For example:
x = np.array([1])
Has a length of 1. However your array does not. Being just a number, you may utilize it right away! Example
x = np.array(3)
y = x + 3
print y
Will yield 3.
The length of x will yield an error because while this is an array, it is technically a zero dimensional array. Hence a length cannot be recovered from this variable.

Related

Strange comportement of list/array

I want to understand why the comportement of my array is like that:
import numpy as np
import math
n=10
P=np.array([[0]*n]*n)
P[2][2]=1 #It works as I want
for i in range(n):
for j in range(n):
P[i][j]=math.comb(n,j+1)*((i+1)/n)**(j+1)*(1-(i+1)/n)**(n-j-1)
print(math.comb(n,j+1)*((i+1)/n)**(j+1)*(1-(i+1)/n)**(n-j-1))
print(P)
I get as a result for P an array with only 0 except 1 for the (n,n) position but values printed are not 0.
I suppose it comes from the fact that I use [[0]*n]*n for my list with mutable/immutable variable because it works well when I use np.zeros() but I don't understand why it works when I set value manually (with P[2][2]=1 for example)
Thanks
The way you are creating the array is defaulting to an integer dtype because it uses the first value to determine the type if you don't explicitly set it. You can demonstrate this by trying to assign a float instead of an int with
P[2][2]=1 #It works as I want
P[2][2]=0.3 #It doesn't work
To use your approach you need to create an array with a dtype of float so values don't get clipped: P=np.array([[0.0]*n]*n) or P=np.array([[0]*n]*n, dtype=float).
This will produce an array of the expected values:
array([[3.87420489e-01, 1.93710245e-01, 5.73956280e-02, 1.11602610e-02,
1.48803480e-03, 1.37781000e-04, 8.74800000e-06, 3.64500000e-07,
9.00000000e-09, 1.00000000e-10],
[2.68435456e-01, 3.01989888e-01, 2.01326592e-01, 8.80803840e-02,
2.64241152e-02, 5.50502400e-03, 7.86432000e-04, 7.37280000e-05,
4.09600000e-06, 1.02400000e-07],
...

setting an array element with a sequence error in python

I started studying python and I have a question for the program. I am writing
as the first step I thought of creating a big matrix and a big vectors where I will put some smaller vectors and smaller matrices. I created at random.
I have created a function that returns the max eigen values of those small matrices and save them in a vector. Also I created a function that basically does the multiplication of the transpose of my small vectors with the small matrices that I had randomly calculated. However when I try to pass the value of the multiplication, I get the following error
"setting an array element with a sequence."
import numpy as np
from scipy import linalg as lg
import math
N=5;
n=3;
Qs=np.zeros((n,N*n))
xs=np.zeros(n*N)
qs=np.zeros(n*N)
grads=np.zeros(N*n)
Lfi=np.zeros(N)
pis=np.zeros(N*n)
pi=np.zeros(N)
phat=np.zeros(N)
j=0;
gamma=np.zeros(N)
def gradient(Q,x) :
return x.transpose().dot(Q)
def eigen(Q):
val, vec = lg.eig(Q)
return np.amax(Q)
for i in range(0,N):
A = np.random.randint(10, size=(n,n))
Qs[0:n,j:j+n] += A
x = np.random.randint(10, size=(n))
qs[j:j+n] += x
x = np.random.randint(10, size=(n))
xs[j:j+n] += x
j = j+n
Lfi[i] = eigen(A)
grads[i] = gradient(A,x)
Why do I get the error for the gradient and not for example at the Lfi?
Your gradient function returns something else than what is expected by grads. From the error message I can tell that grads is numpy array which is not as forgiving as default python list. It has a type associated with it and it requires every element to be of that type.
e.g.
a = np.array([0] * 10)
print(type(a[0]))
this will tell you that the type of elements in this array is numpy.int64 (obviously there are many types and this is just a one of them). If you try to assign some value of a different type, python will try to coerce it to numpy.int64. But obviously, there is no sensible (general) way to coerce another array or matrix to a single number.
If you try
a[0] = [1, 2, 3]
then you will receive the error mentioned by you
ValueError: setting an array element with a sequence.
And why don't you receive the error when calling eigen function? Well, because it just returns a single value, not an array. np.amax(Q) returns a single value if you don't specify axis parameter which is set to None by default.

Trying to convert a MATLAB array to a Python array

I have this MATLAB code that I need to translate to python, however there is an issue in creating a new column in the firings array. In MATLAB, the code creates an n*2 matrix that is initially empty and I want to be able to do the same in python. Using NumPy, I created fired = np.where(v >= 30). However python creates a tuple rather than an array so it throws an error:
TypeError: unsupported operand type(s) for +: 'int' and 'tuple'
This is the code I have in MATLAB that I would like converted into Python
firings=[];
firings=[firings; t+0*fired, fired];
Help is appreciated! Thanks!
np.where generates a two-element tuple if the array is 1D in nature. For the 1D case, you would need to access the first element of the result of np.where only:
fired = np.where(v >= 30)[0]
You can then go ahead and concatenate the matrices. Also a suggestion provided by user #Divakar would be to use np.flatnonzero which would equivalently find the non-zero values in a NumPy array and flattened into a 1D array for less headaches:
fired = np.flatnonzero(v >= 30)
Take note that the logic to concatenate would not work if there were no matches found in fired. You will need to take this into account when you look at your concatenating logic. The convenient thing with MATLAB is that you're able to concatenate empty matrices and the result is no effect (obviously).
Also note that there is no conception of a row vector or column vector in NumPy. It is simply a 1D array. If you want to specifically force the array to be a column vector as you have it, you need to introduce a singleton axis in the second dimension for you to do this. Note that this only works provided that np.where gave you matched results. After, you can use np.vstack and np.hstack to vertically and horizontally concatenate arrays to help you do what you ask. What you have to do first is create a blank 2D array, then do what we just covered:
firings = np.array([[]]) # Create blank 2D array
# Some code here...
# ...
# ...
# fired = find(v >= 30); % From MATLAB
fired = np.where(v >= 30)[0]
# or you can use...
# fired = np.flatnonzero(v >= 30)
if np.size(fired) != 0:
fired = fired[:, None] # Introduce singleton axis
# Update firings with two column vectors
# firings = [firings; t + 0 * fired, fired]; % From MATLAB
firings = np.vstack([firings, np.hstack([t + 0*fired, fired])])
Here np.size finds the total number of elements in the NumPy array. If the result of np.where generated no results, the number of elements in fired should be 0. Therefore the if statement only executes if we have found at least one element in v subject to v >= 30.
If you use numpy, you can define an ndarray:
import numpy as np
firings=np.ndarray(shape=(1,2)
firings[0][0:]=(1.,2.)
firings=np.append(firings,[[3.,4.]],axis=0)

How to build a numpy array row by row in a for loop?

This is basically what I am trying to do:
array = np.array() #initialize the array. This is where the error code described below is thrown
for i in xrange(?): #in the full version of this code, this loop goes through the length of a file. I won't know the length until I go through it. The point of the question is to see if you can build the array without knowing its exact size beforehand
A = random.randint(0,10)
B = random.randint(0,10)
C = random.randint(0,10)
D = random.randint(0,10)
row = [A,B,C,D]
array[i:]= row # this is supposed to add a row to the array with A,C,B,D as column values
This code doesn't work. First of all it complains: TypeError: Required argument 'object' (pos 1) not found. But I don't know the final size of the array.
Second, I know that last line is incorrect but I am not sure how to call this in python/numpy. So how can I do this?
A numpy array must be created with a fixed size. You can create a small one (e.g., one row) and then append rows one at a time, but that will be inefficient. There is no way to efficiently grow a numpy array gradually to an undetermined size. You need to decide ahead of time what size you want it to be, or accept that your code will be inefficient. Depending on the format of your data, you can possibly use something like numpy.loadtxt or various functions in pandas to read it in.
Use a list of 1D numpy arrays, or a list of lists, and then convert it to a numpy 2D array (or use more nesting and get more dimensions if you need to).
import numpy as np
a = []
for i in range(5):
a.append(np.array([1,2,3])) # or a.append([1,2,3])
a = np.asarray(a) # a list of 1D arrays (or lists) becomes a 2D array
print(a.shape)
print(a)

Issue obtaining minimum value of list/array

I'm having a weird issue, at least I can't explain the reason for this behaviour.
I generate a list of random values with the function rand_data as defined below. When I attempt to extract the minimum value using the min() function, it returns the whole list, which leads me to believe it is not a list but an array.
But if I attempt to use the .min() attribute it returns the error:
AttributeError: 'list' object has no attribute 'min'
What is happening here? Is x1 a list or an array?
Minimal working example:
import numpy as np
def rand_data():
return np.random.uniform(low=10., high=20., size=(10,))
# Generate data.
x1 = [rand_data() for i in range(1)]
print min(x1)
print x1.min()
You used a list comprehension:
x1 = [rand_data() for i in range(1)]
You now have a Python list object containing one result from rand_data().
Since rand_data() uses numpy.random.uniform() that means you have a list containing a numpy array.
Don't use a list comprehension here, it is clearly not what you wanted:
x1 = rand_data()
import numpy as np
def rand_data(num_elements):
# numpy returns always an array with a defined number
# of elements specified by the size parameter
return np.random.uniform(low=10., high=20., size=num_elements)
#rand_data will automatically generate the random data for you
# simply specifying the number of elements to generate
x1 = rand_data(10)
print('Minimum value for {0} is {1}'.format(x1, min(x1)))

Categories