Shift a list in Python - python

How would you shift left a list by x in Python, and fill the empty values with zeros?
shift left by 1
input: [1, 2, 3, 4]
output: [2, 3, 4, 0]
shift left by 2
input [1, 2, 3, 4]
output [3, 4, 0, 0]

As far as I'm concerned, there's no 'easy' way, since Python's lists are not constrained by a size, but you can easily implement an algorithm which handles this:
def shift_left(arr, n):
return arr[n:] + [0 for _ in range(n)]
or a bit more consise:
def shift_left(arr, n):
return arr[n:] + [0] * n

You can concat two lists as:
arr[shift:]+[0]*shift
Or if you are a fan of chaining like me:
arr[shift:].__add__([0]*shift)

You can combine numpy's append and roll methods:
import numpy as np
def shift_left(x_, r):
return np.append(np.roll(x_, -r)[:-r], [0 for _ in range(0, r)])
print(shift_left([1, 2, 3, 4], 1))
print(shift_left([1, 2, 3, 4], 2))
Result:
[2 3 4 0]
[3 4 0 0]
Explanation
When you use roll on a list:
print(np.roll([1, 2, 3, 4], -2))
Result:
[3 4 1 2]
You move the each element to the left by r times (r= -2). But we don't want the last r elements so:
print(np.roll([1, 2, 3, 4], -2)[:-2])
Result:
[3 4]
We want the last r values to be 0. So we can append r 0 to the end of the array.
print(np.append(np.roll([1, 2, 3, 4], -2)[:-2], [0 for _ in range(0, 2)]))
Result:
[3 4 0 0]

Related

Python Dataframe subtract a value from each list of a row

I have a data frame consisting of lists as elements. I want to subtract a value from each list and create a new column.
My code:
df = pd.DataFrame({'A':[[1,2],[4,5,6]]})
df
A
0 [1, 2]
1 [4, 5, 6]
# lets substract 1 from each list
val = 1
df['A_new'] = df['A'].apply(lambda x:[a-b for a,b in zip(x[0],[val]*len(x[0]))],axis=1)
Present solution:
IndexError: index 3 is out of bounds for axis 0 with size 2
Expected solution:
df
A A_new
0 [1, 2] [0, 1]
1 [4, 5, 6] [3, 4, 5]
Convert to numpy array
df['A_new'] = df.A.map(np.array)-1
Out[455]:
0 [0, 1]
1 [3, 4, 5]
Name: A, dtype: object
df['A_new'] = df['A'].apply(lambda x:[a-b for a,b in zip(x,[val]*len(x))])
You have to pass the list to the len function. Here x is the list itself. So indexing it, x[0] just returns a number which is wrong given the context. This gives the output:
A A_new
0 [1, 2] [0, 1]
1 [4, 5, 6] [3, 4, 5]
How about a simple list comprehension:
df['new'] = [[i - 1 for i in l] for l in df['A']]
A new
0 [1, 2] [0, 1]
1 [4, 5, 6] [3, 4, 5]
You can convert the list to np.array and then subtract the val:
import numpy as np
df['A_new'] = df['A'].apply(lambda x: np.array(x) - val)
Output:
A A_new
0 [1, 2] [0, 1]
1 [4, 5, 6] [3, 4, 5]

The copy of a list is not being iterated through all the elements

t=[1,2,3,5,2,1]
j=t.copy()
for f in j:
print(f)
j.remove(f)
print(j)
Output
1
[2, 3, 5, 2, 1]
3
[2, 5, 2, 1]
2
[5, 2, 1]
I have a list t and I create a copy of it in j by calling t.copy().
But when I use the looping constructs, it does not traverse through all the elements.
For example, in the output it selects 1, removes it and then prints the list without that element.
After that it should choose 2 which is the next element and remove the same, but it selects 3 instead and 5 in the next iteration.
What could possibly be the reason for this alternate selection? Perhaps this is quite simple, but I am unable to figure the reason out.
The issue is that while you're iterating through the list you're also editing it leading to errors. Instead of iterating through j iterate through t since it'll remain the same throughout iterations.
Code:
t = [1, 2, 3, 5, 2, 1]
j = t.copy()
for f in t:
print(f)
j.remove(f)
print(j)
Output:
1
[2, 3, 5, 2, 1]
2
[3, 5, 2, 1]
3
[5, 2, 1]
5
[2, 1]
2
[1]
1
[]

Translate integers in a numpy array to a contiguous range 0...n

I would like to translate arbitrary integers in a numpy array to a contiguous range 0...n, like this:
source: [2 3 4 5 4 3]
translating [2 3 4 5] -> [0 1 2 3]
target: [0 1 2 3 2 1]
There must be a better way to than the following:
import numpy as np
"translate arbitrary integers in the source array to contiguous range 0...n"
def translate_ids(source, source_ids, target_ids):
target = source.copy()
for i in range(len(source_ids)):
x = source_ids[i]
x_i = source == x
target[x_i] = target_ids[i]
return target
#
source = np.array([ 2, 3, 4, 5, 4, 3 ])
source_ids = np.unique(source)
target_ids = np.arange(len(source_ids))
target = translate_ids(source, source_ids, target_ids)
print "source:", source
print "translating", source_ids, '->', target_ids
print "target:", target
What is it?
IIUC you can simply use np.unique's optional argument return_inverse, like so -
np.unique(source,return_inverse=True)[1]
Sample run -
In [44]: source
Out[44]: array([2, 3, 4, 5, 4, 3])
In [45]: np.unique(source,return_inverse=True)[1]
Out[45]: array([0, 1, 2, 3, 2, 1])
pandas.factorize is one method:
import pandas as pd
lst = [2, 3, 4, 5, 4, 3]
res = pd.factorize(lst, sort=True)[0]
# [0 1 2 3 2 1]
Note: this returns a list, while np.unique will always return an np.ndarray.

square root of sum of square of columns in multidimensional array

I am using multidimensional list with numpy
I have a list.
l = [[0 2 8] [0 2 7] [0 2 5] [2 4 5] [ 8 4 7]]
I need to find square root of sum of square of columns.
0 2 8
0 2 7
0 2 5
2 4 5
8 4 7
output as,
l = [sqrt((square(0) + square(0) + square(0) + square(2) + square(8)) sqrt((square(2) + square(2) + square(2) + square(4) + square(4)) sqrt((square(8) + square(7) + square(5)) + square(5) + square(7))]
>>> import numpy as np
>>> a = np.array([[0, 2, 8], [0, 2, 7], [0, 2, 5], [2, 4, 5], [ 8, 4, 7]])
>>> np.sqrt(np.sum(np.square(a), axis=0))
array([ 8.24621125, 6.63324958, 14.56021978])
>>> import numpy as np
>>> np.sum(np.array(l)**2,axis=0)**.5
array([ 10.67707825, 3.46410162, 11.74734012])
Use the standard function numpy.linalg.norm for this...
import numpy as np
a = np.array([[0, 2, 8], [0, 2, 7], [0, 2, 5], [2, 4, 5], [ 8, 4, 7]])
np.linalg.norm(a,axis=0)
gives:
array([ 8.24621125, 6.63324958, 14.56021978])
What you want to do is use map/reduce
In theory in can be done using nested for loops but could be done in a more functional way...
for l in matrix:
sum all elements**2 in
return the squar root of the sum
A one liner:
map(lambda x: sqrt(lambda r, z: r + z**2, x), matrix)
But to make it more clear, you could rewrite it as such:
def SumOfSquare(lst):
return reduce(lambda r, x: r + x**2, lst)
def ListOfRoot(lst):
return map(lambda x: SumOfSquare(x), lst)
s = ListOfRoot(matrix)
Misread the question, it's without numpy.

How to use numpy's hstack?

I have one large numpy.ndarray array that I want to extract the 4th and 5th columns out of and put those columns into a 2D array. The [i,0] element should be the value on the 4th column and [i,1] should be the element from the 5th column.
I trying to use the numpy.hstack function to do this.
a = numpy.asarray([1, 2, 3, 4, 5])
for i in range(5):
a = numpy.vstack([a, numpy.asarray([1, 2, 3, 4, 5])])
combined = np.hstack([a[:,3], a[:,4]])
However, this simply gives me an nx1 array. I have tried multiple approaches using concatenate that look like these examples:
combined = np.concatenate([a[:,3], a[:,4]])
combined = np.concatenate([a[:,3], a[:,4]], axis=1)
combined = np.concatenate([a[:,3].T, a[:,4].T])
I feel like hstack is the function I want, but I can't seem to figure out how to make it give me an nx2 array. Can anyone point me in the right direction? Any help is appreciated.
Just slice out your data as follows:
X = [[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]]
slicedX = X[:,3:5]
results in:
[[3 4]
[3 4]
[3 4]
[3 4]]
I think this will do what you want:
a[:,[3,4]]
You can also use zip:
>>> c = numpy.array( zip( a[:, 3], a[:, 4]) )
>>> c
array([[4, 5],
[4, 5],
[4, 5],
[4, 5],
[4, 5],
[4, 5]])

Categories