simple but weird vstack/concatenate problems (python) - python

I've been reading over the documentation on numpy arrays and some of it is not making sense.
For instance, the answer given here suggest to use np.vstack or np.concatenate to combine arrays, as does many other places on the internet.
However, when I try to do this with converted lists to np.arrays is doesn't work:
"
>>> some_list = [1,2,3,4,5]
>>> np.array(some_list)
array([1, 2, 3, 4, 5])
>>> some_Y_list = [2,1,5,6,3]
>>> np.array(some_Y_list)
array([2, 1, 5, 6, 3])
>>> dydx = np.diff(some_Y_list)/np.diff(some_list)
>>> np.vstack([dydx, dydx[-1]])"
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
np.vstack([dydx, dydx[-1]])
File "C:\Python27\lib\site-packages\numpy\core\shape_base.py", line 226, in vstack
return _nx.concatenate(map(atleast_2d,tup),0)
ValueError: array dimensions must agree except for d_0
Any way that I can do this?
All I am needing this for in this instance is just to make the derivatives of any order the same shape as my X array given by the user so I can do processing.
Thanks for any help.

The following won't work except in some very limited circumstances:
np.vstack([dydx, dydx[-1]])
Here, dydx is an array and dydx[-1] is a scalar.
It's unclear what you're trying to achieve, but did you perhaps mean to stack them horizontally:
np.hstack([dydx, dydx[-1]])
?
In [38]: np.hstack([dydx, dydx[-1]])
Out[38]: array([-1, 4, 1, -3, -3])

Related

Appending successive rows to Python dataframe

I want to create a bidimensional numpy array.
I tried this:
import numpy as np
result = np.empty
np.append(result, [1, 2, 3])
np.append(result, [4, 5, 9])
1.The dimensions of the array are: (2, 3). How can I get them?
I tried:
print(np.shape(result))
print(np.size(result))
But this prints:
()
1
2.How can I access a specific element in the array?
I tried this:
print(result.item((1, 2)))
But this returns:
Traceback (most recent call last):
File "python", line 10, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute 'item'
Ideally you should be testing this sort of code in an interactive session, where you can easily get more information on the steps. I'll illustrate in ipython.
In [1]: result = np.empty
In [2]: result
Out[2]: <function numpy.core.multiarray.empty>
This is a function, not an array. The correct use is result = np.empty((3,)). That is you have to call the function with a desired size parameter.
In [3]: np.append(result, [1,2,3])
Out[3]: array([<built-in function empty>, 1, 2, 3], dtype=object)
append has created an array, but look at the contents - the function and 3 numbers. And the dtype. Also np.append returns a result. It does not work in-place.
In [4]: result.item((1,2))
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-51f2b4be4f43> in <module>()
----> 1 result.item((1,2))
AttributeError: 'builtin_function_or_method' object has no attribute 'item'
Your error tells us that result is a function, not an array. The same thing you set at the start.
In [5]: np.shape(result)
Out[5]: ()
In [6]: np.array(result)
Out[6]: array(<built-in function empty>, dtype=object)
In this case the function versions of np.shape and np.size aren't diagnostic, because they first convert result into an array. result.shape would have given an error.
The underlying problem is that you are using a list model
result = []
result.append([1,2,3])
result.append([4,5,6])
But the array append is misnamed, and misused. It is just a front end to np.concatenate. If you don't understand concatenate, you probably won't use np.append right. In fact, I would argue that you shouldn't use np.append at all.
The correct way to use append is to start with an array that has size 0 dimension, and reuse the result:
In [7]: result = np.empty((0,3),int)
In [8]: result
Out[8]: array([], shape=(0, 3), dtype=int32)
In [9]: result = np.append(result,[1,2,3])
In [10]: result
Out[10]: array([1, 2, 3])
In [11]: result = np.append(result,[4,5,6])
In [12]: result
Out[12]: array([1, 2, 3, 4, 5, 6])
But maybe that isn't what you want? Even I'm misusing append.
Back to the drawing board:
In [15]: result = []
In [16]: result.append([1,2,3])
In [17]: result.append([4,5,6])
In [18]: result
Out[18]: [[1, 2, 3], [4, 5, 6]]
In [19]: result = np.array(result)
In [20]: result
Out[20]:
array([[1, 2, 3],
[4, 5, 6]])
With a real array, your item expression works, though usually we use [] indexing:
In [21]: result[1,2]
Out[21]: 6
In [22]: result.item((1,2))
Out[22]: 6
Source code for np.append (note the use of np.concatenate):
In [23]: np.source(np.append)
In file: /usr/local/lib/python3.5/dist-packages/numpy/lib/function_base.py
def append(arr, values, axis=None):
"""
...
"""
arr = asanyarray(arr)
if axis is None:
if arr.ndim != 1:
arr = arr.ravel()
values = ravel(values)
axis = arr.ndim-1
return concatenate((arr, values), axis=axis)
That's not quite the way to use numpy arrays. empty is a function. append, for example, returns new arrays, but you're ignoring the return value.
To create the 2-d array, use this:
In [3]: result = np.array([[1, 2, 3], [4, 5, 9]])
To find its shape:
In [4]: result.shape
Out[4]: (2, 3)
To access a specific element:
In [5]: result[1][2]
Out[5]: 9

How to get an array with one dimension in python ?

I need to have each numpy file from a folder like an array with 1 dimension; This is my code:
path ='E:\\t'
traces= os.listdir(path)
print("tempTracesHW_Creation=", tempTracesHW)
for i in range(len(traces)):
HW = tempHW[i]
for trace in os.listdir(path):
file_array= np.load(os.path.join(path, trace))
print file_array
tempTracesHW[HW].append(file_array)
The result of file_array is:
file_array= [[-0.0006447 -0.00094265 -0.0012406 ..., -0.02096185 -0.0210646
-0.02114679]]
But what I want is:
file_array= [-0.0006447 -0.00094265 -0.0012406 ..., -0.02096185 -0.0210646
-0.02114679]
I would be very grateful if you could help me please?
The numpy load function loads the file and return the array.
The file_array is two dimensional because your input to numpy.load is two dimensional.
Check the trace file, you need to make it one-dimensional array.
For example:
example = numpy.save("example",numpy.array([1,2,3]))
result = numpy.load("example.npy")
print result
[1,2,3]
See if this helps.
More of the code snippet would have help understanding your problem.(About the Trace file)
You can use flatten to turn this (1, x) array into a (x, ) array. flatten can be used differently, but in this case, it will do what you're looking for.
>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4, 5]])
>>> a
array([[1, 2, 3, 4, 5]])
>>> a.shape
(1, 5)
>>> a.flatten()
array([1, 2, 3, 4, 5])
>>> a.flatten().shape
(5,)

Means of asymmetric arrays in numpy

I have an asymmetric 2d array in numpy, as in some arrays are longer than others, such as: [[1, 2], [1, 2, 3], ...]
But numpy doesn't seem to like this:
import numpy as np
foo = np.array([[1], [1, 2]])
foo.mean(axis=1)
Traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/tom/.virtualenvs/nlp/lib/python3.5/site-packages/numpy/core/_methods.py", line 56, in _mean
rcount = _count_reduce_items(arr, axis)
File "/home/tom/.virtualenvs/nlp/lib/python3.5/site-packages/numpy/core/_methods.py", line 50, in _count_reduce_items
items *= arr.shape[ax]
IndexError: tuple index out of range
Is there a nice way to do this or should I just do the maths myself?
We could use an almost vectorized approach based upon np.add.reduceat that takes care of the irregular length subarrays, for which we are calculating the average values. np.add.reduceat sums up elements in those intervals of irregular lengths after getting a 1D flattened version of the input array with np.concatenate. Finally, we need to divide the summations by the lengths of those subarrays to get the average values.
Thus, the implementation would look something like this -
lens = np.array(map(len,foo)) # Thanks to #Kasramvd on this!
vals = np.concatenate(foo)
shift_idx = np.append(0,lens[:-1].cumsum())
out = np.add.reduceat(vals,shift_idx)/lens.astype(float)
You could perform the mean for each sub-array of foo using a list comprehension:
mean_foo = np.array( [np.mean(subfoo) for subfoo in foo] )
As suggested by #Kasramvd in another answer's comment, you can also use the map function :
mean_foo = np.array( map(np.mean, foo) )

create numpy array by appending a number to another numpy array

This supposedly simple task is driving me a bit mad.
Say you want to create an array by concatenating an integer to another array:
import numpy as np
a = 4
b = np.array([1, 10, 24, 12])
A = np.array(a, b)
gives me TypeError: data type not understood. Which I understand because I'm mixing an integer with a list. Now if I do A = np.array([a], b) I get the same result, if I get A = np.array([a] + b) I don't get the expected result.
Also, I tried A = np.array([a, *b]) with SyntaxError: can use starred expression only as assignment target.
How's the proper way to do this?
What's wrong with using np.append?:
In [20]:
a = 4
b = np.array([1, 10, 24, 12])
np.append(a,b)
Out[20]:
array([ 4, 1, 10, 24, 12])
You can use the concatenate function to do this
A = np.concatenate(([a], b))
For your case, I think using append is "better" since it is less error prone as it accepts scalars as well, (as my own mistake clearly shows!) and (arguably) slightly more readable.
You can also use hstack (http://docs.scipy.org/doc/numpy/reference/generated/numpy.hstack.html):
In [194]: a = 4
In [195]: b = np.array([1, 10, 24, 12])
In [196]: np.hstack((a,b))
Out[196]: array([ 4, 1, 10, 24, 12])
hstack has the advantage that it can concatenate as many arrays/lists as you want (e.g. np.hstack((a, b, a, b, [0, 2, 4, 6, 8])))

Python function to accept numpy ndarray or sequence as arguments

I have seen some python functions that work generally receiving a (n,2) shaped numpy ndarray as argument, but can also "automagically" receive (2,n) or even len(2) sequences (tuple or list).
How is it pythonically achieved? Is there a unified good practice to check and treat these cases (example, functions in numpy and scipy module), or each developer implements which he thinks best?
I'd just like to avoid chains of (possibly nested) chains of ifs/elifs, in case there is a well known better way.
Thanks for any help.
You can use the numpy.asarray function to convert any sequence-like input to an array:
>>> import numpy
>>> numpy.asarray([1,2,3])
array([1, 2, 3])
>>> numpy.asarray(numpy.array([2,3]))
array([2, 3])
>>> numpy.asarray(1)
array(1)
>>> numpy.asarray((2,3))
array([2, 3])
>>> numpy.asarray({1:3,2:4})
array({1: 3, 2: 4}, dtype=object)
It's important to note that as the documentation says No copy is performed if the input is already an ndarray. This is really nice since you can pass an existing array in and it just returns the same array.
Once you convert it to a numpy array, just check the length if that's a requirement. Something like:
>>> def f(x):
... x = numpy.asarray(x)
... if len(x) != 2:
... raise Exception("invalid argument")
...
>>> f([1,2])
>>> f([1,2,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in f
Exception: invalid argument
Update:
Since you asked, here's a "magic" function that will except *args as an array also:
>>> def f(*args):
... args = numpy.asarray(args[0]) if len(args) == 1 else numpy.asarray(args)
... return args
...
>>> f(7,3,5)
array([7, 3, 5])
>>> f([1,2,3])
array([1, 2, 3])
>>> f((2,3,4))
array([2, 3, 4])
>>> f(numpy.array([1,2,3]))
array([1, 2, 3])

Categories

Resources