Swapping side from an array - python

I have thousand of data in X and Y. I am trying to plot an interpolation graph but to start plotting it need to began from negative value.
x = [15000,14000,13000,12000,11000,0,-1000,-10000,-15000]
y = [1,1,1,1,1,0,-1,-1,-1]
How can i make it into this format
x = [-15000,-10000,-1000,0,11000,12000,13000,14000,15000]
y = [-1,-1,-1,0,1,1,1,1,1]

Try this:
x = x[::-1]
y = y[::-1]
I'd call this "reversing" a list, not "swapping" it, but you get the idea.

Assuming you really need to sort the x list, and also move around the y values in the same way the x values were permuted, take a look at this:
>>> x = [15000,14000,13000,12000,11000,0,-1000,-10000,-15000]
>>> y = [1,1,1,1,1,0,-1,-1,-1]
>>> x1, y1 = zip(*sorted(zip(x, y)))
>>> x1
(-15000, -10000, -1000, 0, 11000, 12000, 13000, 14000, 15000)
>>> y1
(-1, -1, -1, 0, 1, 1, 1, 1, 1)
So x1 and y1 are in the orders you want. But they're tuples instead of lists. If you need lists instead, then, e.g.,
x1, y1 = map(list, zip(*sorted(zip(x, y))))
is one way to do it.
Bwt if all you really need is to simply reverse the lists, then #OscarLopez's answer is much easier :-)

Related

how to overwrite only a portion of the array?

i have an array that contains labels, for instance
X1 = [1, 0, 1, 2, 3, 1, 3, 2, 3, 1, 0]
X1 = np.array(X1)
I also have an array X2 that contains the updated labels for label [1] in X1, for instance.
X2 = [-1, 1, -1, -1]
X2 = np.array(X2)
how to overwrite X1 for all labels equal to [1] to be X2?
The output should look like:
New_X1 = [-1, 0, 1, 2, 3, -1, 3, 2, 3, -1, 0]
I tried something like this:
New_X1 = [np.where(X1==1)]= X2
This obviously didn't work.
Any help, please.
Assuming that the lists you've written down are indeed NumPy arrays, you are not indexing into New_X1 properly. It should be:
New_X1[np.where(X1 == 1)] = X2
However, you can achieve the same thing with logical indexing instead. It's not only cleaner, but faster:
New_X1[X1 == 1] = X2
Here's a nice and concise way to accomplish your task through map():
New_X1 = list(map(lambda x1: x1 if x1 != 1 else X2.pop(0), X1))
EDIT:
I've seen you edited your post specifying that the sequences are np arrays: you can easily adapt this implementation to that case too.
Thank you all for your feedback. All correct.
Here is what i did, based on your feedback.
New_X1 = X1.copy()
New_X1[X1 == 1] = X2

List of tuples of vectors --> two matrices

In Python, I have a list of tuples, each of them containing two nx1 vectors.
data = [(np.array([0,0,3]), np.array([0,1])),
(np.array([1,0,4]), np.array([1,1])),
(np.array([2,0,5]), np.array([2,1]))]
Now, I want to split this list into two matrices, with the vectors as columns.
So I'd want:
x = np.array([[0,1,2],
[0,0,0],
[3,4,5]])
y = np.array([[0,1,2],
[1,1,1]])
Right now, I have the following:
def split(data):
x,y = zip(*data)
np.asarray(x)
np.asarray(y)
x.transpose()
y.transpose()
return (x,y)
This works fine, but I was wondering whether a cleaner method exists, which doesn't use the zip(*) function and/or doesn't require to convert and transpose the x and y matrices.
This is for pure entertainment, since I'd go with the zip solution if I were to do what you're trying to do.
But a way without zipping would be vstack along your axis 1.
a = np.array(data)
f = lambda axis: np.vstack(a[:, axis]).T
x,y = f(0), f(1)
>>> x
array([[0, 1, 2],
[0, 0, 0],
[3, 4, 5]])
>>> y
array([[0, 1, 2],
[1, 1, 1]])
Comparing the best elements of all previously proposed methods, I think it's best as follows*:
def split(data):
x,y = zip(*data) #splits the list into two tuples of 1xn arrays, x and y
x = np.vstack(x[:]).T #stacks the arrays in x vertically and transposes the matrix
y = np.vstack(y[:]).T #stacks the arrays in y vertically and transposes the matrix
return (x,y)
* this is a snippet of my code

Replacing original values

I have a numpy array y which I'm trying to preserve, however is getting replaced by the following operation:
ys = np.unique(y)
y2 = y
for i,val in enumerate(ys):
y2[y2==val]=i
Why is the original numpy array getting replaced by this operation? originally the ys were 1,5,7 and after the above operation np.unique(y) gives: 0,1,2
As already stated, y2 = y simply makes another reference to the underlying numpy array. As far as python is concerned, y2 and y are indistinguishable. You can even check y2 is y will return True and both arrays have the same id (memory location). As noted in the comments, you can make y2 a copy of y which does not share the same memory address:
y2 = y.copy()
Alternatively (and perhaps more efficient), you can rely on builtin numpy functions. In this case, I think that numpy.digitize might suit your needs:
np.digitize(y, np.unique(y)) - 1
Seems to do the trick.
>>> a = np.array([0, 0, 1, 2, 1, 3, 4, 5, 0, 10, 30])
>>> b = np.digitize(a, np.unique(a)) - 1
>>> b
array([0, 0, 1, 2, 1, 3, 4, 5, 0, 6, 7])
It's because when you do y2[y2==val]=i you're manipulating the original array y. Python doesn't copy np array's unless you explicitly tell it to as #John Galt mentioned.
Instead of doing y2 = y do y2 = y.copy(). This will create a copy of y and you'll be manipulating the copy instead of the original.

Creating an X by Y dimension array of (a,b) points in Python 2.7

I've been oddly bashing my head against this problem for several hours, and would appreciate any help!
I would like to create a (for example) 100x100 array in which each index is a (x,y) coordinate. The overall goal here is the following:
I have x,y coordinates and would like to arrange them in a 2D space so that I can use the np.diagonal function to return the (x,y) coordinates along a line. I'll then use those (x,y) points to compare particular values.
The first step here is actually creating the array and I just can't seem to do it.
I'm not sure about the numpy part of your request, but you can create the array like so:
coords = [[(y,x) for x in range(100)] for y in range(100)]
>>> coords[50][2]
(50,2)
If you just want the values along the diagonal, why dont you just create a 1D list?
import numpy as np
xs = np.linspace(1,10,100) # assuming x goes form 1 to 10
ys = np.linspace(2,3, 100) # assuming y goes from 2 to 3
xy = zip(xs, ys)
You no longer need the 2d array and then call the diagonal.
Working on Jaime's suggestion:
>>> x, y = numpy.mgrid[0:100, 0:100]
>>> z = numpy.array([x, y]).transpose([1,2,0])
>>> z[50, 2]
array([50, 2])
EDIT: Given an array of points p, of the shape (2, P), this is how you would find out which of these points are underneath diagonal n:
>>> d = numpy.diagonal(z, n)
>>> cond0 = p[0, None] < d[0, :, None]
>>> cond1 = p[1, None] < d[1, :, None]
>>> good_indices_full = numpy.where(numpy.logical_and(cond0, cond1))
>>> good_indices = good_indices_full[1]
(I prefer to work with "good_indices", i.e. write stuff like p[:, good_indices], rather than the full tuple of arrays that numpy.where gives back).

How can I broadcast between 1D and nD arrays to obtain a (1+n)D array output?

I have an n-dimensional ndarray z0, and a 1-dimensional ndarray za. The sizes don't correspond to each other in any way. I'd like to be able to create a new n+1-dimensional array, z, where z[i]=z0+za[i]. Is there some simple way to do this with broadcasting?
This is not equivalent to this question. If z0 is 2D, this can be easily achieved as follows:
z0[np.newaxis]+norm.ppf(alphas)[:,None]
However, I need to be able to do this regardless of z0's dimensionality, and so simply adding the correct number of None or np.newaxis terms won't work.
How about:
z = za.reshape(za.shape + (1,)*z0.ndim) + z0
For example:
import numpy as np
z0 = np.ones((2, 3, 4, 5))
za = np.ones(6)
z = za.reshape(za.shape + (1,)*z0.ndim) + z0
print z.shape
# (6, 2, 3, 4, 5)
Maybe something like
>>> z0 = np.random.random((2,3,4))
>>> za = np.random.random(5)
>>> z = np.rollaxis((z0[...,None] + za), -1)
>>> z.shape
(5, 2, 3, 4)
>>> [np.allclose(z[i], z0 + za[i]) for i in range(len(za))]
[True, True, True, True, True]
where I've used ... to mean any number of dimensions, and rollaxis to put it in the shape I think you want. If you don't mind the new axis being at the end, you could get away with z0[..., None] + za, I think.

Categories