How to sum columns of an array in Python - python

How do I add up all of the values of a column in a python array? Ideally I want to do this without importing any additional libraries.
input_val = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
output_val = [3, 6, 9, 12, 15]
I know I this can be done in a nested for loop, wondering if there was a better way (like a list comprehension)?

zip and sum can get that done:
Code:
[sum(x) for x in zip(*input_val)]
zip takes the contents of the input list and transposes them so that each element of the contained lists is produced at the same time. This allows the sum to see the first elements of each contained list, then next iteration will get the second element of each list, etc...
Test Code:
input_val = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
print([sum(x) for x in zip(*input_val)])
Results:
[3, 6, 9, 12, 15]

In case you decide to use any library, numpy easily does this:
np.sum(input_val,axis=0)

You may also use sum with zip within the map function:
# In Python 3.x
>>> list(map(sum, zip(*input_val)))
[3, 6, 9, 12, 15]
# explicitly type-cast it to list as map returns generator expression
# In Python 2.x, explicit type-casting to list is not needed as `map` returns list
>>> map(sum, zip(*input_val))
[3, 6, 9, 12, 15]

Try this:
input_val = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
output_val = [sum([i[b] for i in input_val]) for b in range(len(input_val[0]))]
print output_val

Please construct your array using the NumPy library:
import numpy as np
create the array using the array( ) function and save it in a variable:
arr = np.array(([1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]))
apply sum( ) function to the array specifying it for the columns by setting the axis parameter to zero:
arr.sum(axis = 0)

This should work:
[sum(i) for i in zip(*input_val)]

I guess you can use:
import numpy as np
new_list = sum(map(np.array, input_val))

I think this is the most pythonic way of doing this
map(sum, [x for x in zip(*input_val)])

One-liner using list comprehensions: for each column (length of one row), make a list of all the entries in that column, and sum that list.
output_val = [sum([input_val[i][j] for i in range(len(input_val))]) \
for j in range(len(input_val[0]))]

Try this code. This will make output_val end up as [3, 6, 9, 12, 15] given your input_val:
input_val = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
vals_length = len(input_val[0])
output_val = [0] * vals_length # init empty output array with 0's
for i in range(vals_length): # iterate for each index in the inputs
for vals in input_val:
output_val[i] += vals[i] # add to the same index
print(output_val) # [3, 6, 9, 12, 15]

Using Numpy you can easily solve this issue in one line:
1: Input
input_val = [[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
2: Numpy does the math for you
np.sum(input_val,axis=0)
3: Then finally the results
array([ 3, 6, 9, 12, 15])

output_val=input_val.sum(axis=0)
this would make the code even simpler I guess

You can use the sum function instead of np.sum simply.
input_val = np.array([[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]])
sum(input_val)
output: array([ 3, 6, 9, 12, 15])

Related

Shuffling two 2D tensors in PyTorch and maintaining same order correlation

Is it possible to shuffle two 2D tensors in PyTorch by their rows, but maintain the same order for both? I know you can shuffle a 2D tensor by rows with the following code:
a=a[torch.randperm(a.size()[0])]
To elaborate:
If I had 2 tensors
a = torch.tensor([[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3]])
b = torch.tensor([[4, 4, 4, 4, 4],
[5, 5, 5, 5, 5],
[6, 6, 6, 6, 6]])
And ran them through some function/block of code to shuffle randomly but maintain correlation and produce something like the following
a = torch.tensor([[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1],
[3, 3, 3, 3, 3]])
b = torch.tensor([[5, 5, 5, 5, 5],
[4, 4, 4, 4, 4],
[6, 6, 6, 6, 6]])
My current solution is converting to a list, using the random.shuffle() function like below.
a_list = a.tolist()
b_list = b.tolist()
temp_list = list(zip(a_list , b_list ))
random.shuffle(temp_list) # Shuffle
a_temp, b_temp = zip(*temp_list)
a_list, b_list = list(a_temp), list(b_temp)
# Convert back to tensors
a = torch.tensor(a_list)
b = torch.tensor(b_list)
This takes quite a while and was wondering if there is a better way.
You mean
indices = torch.randperm(a.size()[0])
a=a[indices]
b=b[indices]
?

How to find a minimum value in a 2D array without using numpy or flattened in Python?

Let's say that:
atable = [[6, 2, 3, 1], [3, 4, 2, 1], [4, 8, 7, 6], [8, 9, 3, 7]]
without using numpy or flattened, how would you find the minimum value of the entire list?
I assume you can use a list but I am not sure.
Here are several approaches:
from itertools import chain
atable = [[6, 2, 3, 1], [3, 4, 2, 1], [4, 8, 7, 6], [8, 9, 3, 7]]
# Flatten the sublists into a single list
result = min(chain.from_iterable(atable))
# Find the min of each list, the find the min of mins
result = min(map(min, atable))
# Use a generator expression with nested loops
result = min(i for lst in atable for i in lst)
Here is a brute force approach:
atable = [[6, 2, 3, 1], [3, 4, 2, 1], [4, 8, 7, 6], [8, 9, 3, 7]]
min_list = []
for l in atable:
min_list.append(min(l))
min_val = min(min_list)
For your specific problem...
min(min(a_table))
As noted by #Prune this does not work. In fact min(a_table) returns the sublist with the smallest first element.

How to perform multiple list slices at the same time?

Say I have a list:
L1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
and I have a list of indices:
indices = (2, 5, 7)
What I would like to be able to do is slice the list at all 3 indices at the same time. In other words, id like to perform the following lines of code in one line:
sub1 = L1[:2]
sub2 = L1[2:5]
sub3 = L1[5:7]
sub4 = L1[7:]
I could fairly easily write a function that does this, but I was wondering if it is possible to do this in one expression.
You could use operator.itemgetter with slice objects:
>>> from operator import itemgetter
>>> get = itemgetter(slice(0, 2), slice(2, 5), slice(5, 7), slice(7, None))
>>> values = range(1, 10)
>>> values
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> get(values)
([1, 2], [3, 4, 5], [6, 7], [8, 9])
Are you looking for a one liner? We could give you one, but I would just keep it simple:
L1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
indices = (2, 5, 7)
start = 0
sections = []
for end in indices:
sections.append(L1[start:end])
start = end
sections.append(L1[start:])
for part in sections:
print part
# [1, 2]
# [3, 4, 5]
# [6, 7]
# [8, 9]
Yes, it can be done in one expression, but it's not very readable:
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
ind = (2, 5, 7)
print([seq[p:q] for p,q in zip((0,)+ind, ind+(len(seq),))])
output
[[1, 2], [3, 4, 5], [6, 7], [8, 9]]
If you really want to assign the sublists to separate names you can do it like this:
s1, s2, s3, s4 = [seq[p:q] for p,q in zip((0,)+ind, ind+(len(seq),))]
but it's probably better to just keep them in a list of lists.
Well, with the help of some built-in functionality you could do it in one line. The 'biggest' problem is transforming the list of end points to a list of (start,end) tuples or slice objects.
The code below extends the endpoints list with 0 on one end and None at the other end and uses zip() to combine pairs of them. Then use the operator.itemgetter() trick to extract the slices:
import operator
ends = [2,5,7]
values = range(20)
operator.itemgetter(*[slice(*z) for z in zip([0]+ends, ends+[None])])(values)
Output:
([0, 1], [2, 3, 4], [5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
List comprehensions are amazing.
Starting with your list:
>>> L1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Pad your indices with None:
>>> indices = (None, 2, 5, 7, None)
Now comprehend away:
>>> [L1[start:stop] for start, stop in zip(indices[:-1], indices[1:])]
[[1, 2], [3, 4, 5], [6, 7], [8, 9]]

How do I use modular arithmetic on indices?

I am trying to create a function that, for each member of a list, returns the value of that member and the number of values either side of it. The only trick is that it has to "wrap around" when it is at the start or end of the list
For example:
a = [0,1,2,3,4,5,6,7,8,9]
myfunc(a,2) # 2 indicates 2 either side
[8,9,0,1,2]
[9,0,1,2,3]
[0,1,2,3,4]
...
...
[6,7,8,9,0]
[7,8,9,0,1]
I can work out how to do it from index 2 until 7:
def myfunc(vals, rnge):
for i in range(0+rnge, len(vals)-rnge):
print vals[i-rnge:i+rnge+1]
But I can't work out how to handle when it needs to wrap around.
you could try this (extend vals in both directions first). there may be something in collections that allows for this to be done more efficiently:
def myfunc(vals, rnge):
vals_ext = vals[-rnge:] + vals + vals[:rnge]
for i in range(len(vals)):
print( vals_ext[i:i+2*rnge+1] )
output:
[8, 9, 0, 1, 2]
[9, 0, 1, 2, 3]
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
[3, 4, 5, 6, 7]
[4, 5, 6, 7, 8]
[5, 6, 7, 8, 9]
[6, 7, 8, 9, 0]
[7, 8, 9, 0, 1]
How about:
def myfunc(vals, rnge):
valsX3 = vals*3;
for i in range(len(vals)):
print valsX3[i:i+2*rnge+1]
You could use something like this to avoid the duplication of arrays:
wrapping around slices in Python / numpy
Not sure how it does it internally though.
Here is an alternative approach you might also find useful:
def myfunc(alist, offset):
adeque = collections.deque(a)
adeque.rotate(offset)
for i in xrange(len(alist)):
print list(itertools.islice(adeque, 0, 2*offset+1))
adeque.rotate(-1)
a = [0,1,2,3,4,5,6,7,8,9]
myfunc(a,2) # 2 indicates 2 either side
It makes use of the deque collections object which has an efficient rotate function.
Generate your lists using the numpy element-wise modulo of an (unshifted) array.
You want 5 elements that wrap around 10, so use modulo 10. For example if the list starts with 8:
np.mod(np.arange(8,8+5,1),10) returns [8, 9, 0, 1, 2]
To get all 10 possible lists, evaluate list(np.mod(np.arange(s,s+5,1),10))for each start s=1,2,..,10
Or, in a single list comprehension without resorting to numpy,
[[t%10 for t in range(s,s+5)] for s in range(10)]
returns
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8],
[5, 6, 7, 8, 9],
[6, 7, 8, 9, 0],
[7, 8, 9, 0, 1],
[8, 9, 0, 1, 2],
[9, 0, 1, 2, 3]]
Here is the solution :
def defunc(vals, start, rnge):
n = len(vals)
new = []
for i in xrange((start - rnge), (start + rnge)+ 1):
new.append(vals[i%n])
return new
def myfunc(vals, rnge):
n = len(vals)
for i in range(n):
print defunc(vals,i,rnge)
I am not slicing the list to make the logic clearer.
I hope this works

Create a matrix with solution arrays in it

I need to create a matrix in Python containing a list of unknown arrays r that have this form:
r_i=[r1,r2,r3,r4,th_12,th_13]
I am running for statements with a couple of if conditions that will give me in output a number of r_i arrays that I don't know from the beginning.
I am looking for a function like append that I normally use to create a vector with all the solutions that I generate, but this time each solution is not a single value but an array of 6 values and I am not able to generate what I want.
I need to create a matrix like this one, where every r_1 has the form of the code that I wrote above.
EDIT: I would like to generate a numpy array (R_tot should be a numpy array).
You can generate the array normally as I explained in my comment:
r_tot = []
for r_i in however_many_rs_there_are: # each r_i contains an array of 6 values
r_tot.append(r_i)
You can then convert r_tot into a numpy array like so:
import numpy
np_array = numpy.array(r_tot)
Here's a very simple proof of concept:
>>> import random, numpy
>>> r_tot = []
>>> for i in range(0,random.randint(1,20)): # append an arbitrary number of arrays
r_i = [1,2,3,4,5,6] # all of size six
r_tot.append(r_i) # to r_tot
>>> np_array = numpy.array(r_tot) # then convert to numpy array!
>>> np_array # did it work?
array([[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6], # yeaaaah
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6]])

Categories

Resources