I have a 2D numpy array of lambda functions. Each function has 2 arguments and returns a float.
What's the best way to pass the same 2 arguments to all of these functions and get a numpy array of answers out?
I've tried something like:
np.reshape(np.fromiter((fn(1,2) for fn in np.nditer(J,order='K',flags=["refs_ok"])),dtype = float),J.shape)
to evaluate each function in J with arguments (1,2) ( J contains the functions).
But it seems very round the houses, and also doesn't quite work...
Is there a good way to do this?
A = J(1,2)
doesn't work!
You can use list comprehensions:
A = np.asarray([[f(1,2) for f in row] for row in J])
This should work for both numpy arrays and list of lists.
I don't think there is a really clean way, but this is reasonably clean and works:
import operator
import numpy as np
# create array of lambdas
a = np.array([[lambda x, y, i=i, j=j: x**i + y**j for i in range(4)] for j in range(4)])
# apply arguments 2 and 3 to all of them
np.vectorize(operator.methodcaller('__call__', 2, 3))(a)
# array([[ 2, 3, 5, 9],
# [ 4, 5, 7, 11],
# [10, 11, 13, 17],
# [28, 29, 31, 35]])
Alternatively, and slightly more flexible:
from types import FunctionType
np.vectorize(FunctionType.__call__)(a, 2, 3)
# array([[ 2, 3, 5, 9],
# [ 4, 5, 7, 11],
# [10, 11, 13, 17],
# [28, 29, 31, 35]])
Related
When using a list, I saw that I cannot add or subtract the sample I took from the list. For example:
import random
x = random.sample ((1 ,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), k=1 )
print(x + 1)
Why I can’t add into the list I created and how can I get around that issue?
If you want to increase the value of every item in a list, you can do like:
import random
x = random.sample ((1 ,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), k=3 )
print(x)
for index in range(len(x)):
x[index] = x[index] +1
print(x)
In your case, if k is always 1, you can simply like:
import random
x = random.sample ((1 ,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), k=1 )
print(x)
x[0] = x[0] + 1
print(x)
The reason you can't concatenate is because the type random.sample is returning is a list of size k=1. If you want to be returning an element of your sequence and add to it, you should be using random.choice. It should read something along the lines of:
import random
x = random.choice((1,2,3,4,5,6,7,8,9,10,11,12,13))
print(x+1)
I would like to know how to calculate the arithmetic mean for all of two consecutive elements in a python-numpy array, and save the values in another array
col1sortedunique = [0.0610754, 0.27365186, 0.37697331, 0.46547072, 0.69995587, 0.72998093, 0.85794189]
thank you
If I understood you correctly you want to do something like this:
import numpy as np
arr = np.arange(0,10)
>>> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
conse_mean = (arr[:-1]+arr[1:])/2
>>> array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5])
so that would be a mapping from an array with length N to one with length N-1.
Maybe an additional explanation of the syntax:
arr[1:])
>>> array([1, 2, 3, 4, 5, 6, 7, 8, 9])
would give you your array from without the first element and
arr[:-1])
>>> array([0,1, 2, 3, 4, 5, 6, 7, 8])
without the last.
Therefore you have two smaller arrays where a element and its consecutive neighbor have the same index and you can just calculate the mean as it is done above.
I want to take input of 2 numbers: the number of rows and the number of columns. I then want to use these to output a matrix numbered sequentially. I want to do this using a list comprehension. The following is a possible output.
>>>> my_matrix = matrix_fill(3, 4)
>>>> my_matrix
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
I am using the following code to output a sequentially numbered list:
def matrix_fill(num_rows, num_col):
list=[i for i in range(num_col)]
return (list)
I cannot, however, figure out how to make the sequential list of numbers break into the separate lists as shown in the output based on num_rows.
I don't think you need itertools for that. The range function can take a step as a parameter. Like this:
def matrix_fill(rows,cols):
return [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)]
And then it works as expected.
>>> matrix_fill(3,4)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
Let's break this down a little bit and understand what's happening.
>>> [x for x in range(1,3*4+1)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
So what we want to do is to get a new slice every four elements.
>>> [x for x in range(1,3*4+1)][0:4]
[1, 2, 3, 4]
>>> [x for x in range(1,3*4+1)][4:8]
[5, 6, 7, 8]
>>> [x for x in range(1,3*4+1)][8:12]
[9, 10, 11, 12]
So we want to iterate over the elements of the list[x for x in range(1,3*4+1)] of length "rows*cols" ( 3 * 4 ), create a new slice every "cols" number of elements, and group these slices under a single list. Therefore, [[x for x in range(1,rows*cols+1)][i:i+cols] for i in range(0,rows*cols,cols)] is a suitable expression.
Nest a list comprehension inside another one, use itertools.count() to generate the sequence:
import itertools
rows = 3
cols = 4
count_gen = itertools.count() # pass start=1 if you need the sequence to start at 1
my_matrix = [[next(count_gen) for c in range(cols)] for r in range(rows)]
print(my_matrix)
# prints: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
# As a function
def matrix_fill(rows, cols):
count_gen = itertools.count()
return [[next(count_gen) for c in range(cols)] for r in range(rows)]
If you used the numpy module, the method is extremely simple, with no list comprehension needed.
my_matrix = np.arange(1, 13).reshape(3,4)
Printing the variable my_matrix shows
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
I have the following function which makes use of a dictionary of cycle_times to generate lists and dictionaries containing elements whose values are greater than a certain threshold.
def anamolous_cycle_time_index_and_lengths(cycle_time_dict, anamoly_threshold):
for meter,cycle_time_list in cycle_time_dict.items():
anamoly_dict = {cycle_time_list.index(x):x for x in cycle_time_list if x > anamoly_threshold}
anamoly_list = [x for x in cycle_time_list if x > anamoly_threshold]
print(meter,len(anamoly_dict))
print([value for key,value in anamoly_dict.items()])
print(anamoly_list)
Suppose I give the inputs as
new_dict = {104:[2,3,4,5,6,7,3,2,5,6,7], 101:[2,45,4,2,5,2,34,2,5,6,7], 106:[2,23,4,5,65,7,3,23,5,6,7]}
anamoly_threshold = 3
The outputs I get are
104 4
[4, 5, 6, 7]
[4, 5, 6, 7, 5, 6, 7]
101 6
[45, 4, 5, 34, 6, 7]
[45, 4, 5, 34, 5, 6, 7]
106 6
[23, 4, 5, 65, 7, 6]
[23, 4, 5, 65, 7, 23, 5, 6, 7]
Shouldn't the list and dictionary give me the same output? I have run a comprehension for both data structures on the same data.
Your problem is the use of .index(x). This returns the index for the first occurrence of x. And since dictionary keys are unique, you will see only the first occurrence of duplicate elements in your dict comprehension.
There are several ways to overcome this problem. The easiest is to use enumerate:
anamoly_dict = {index: x for index, x in enumerate(cycle_time_list) if x > anamoly_threshold}
Now the output for both methods is the same.
Im trying to make a matrix that is 3 rows by 4 columns and includes the numbers 1-12. Would then like to multiply those numbers by a factor to make a new matrix.
def matrix(x):
matrix=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
new_matrix=[[x*1,x*2,x*3],[x*4,x*5,x*6],[x*7,x*8,x*9],[x*10,x*11,x*12]]
print(new_matrix)
This approach works, however it does not use loops, I'm looking for an approach that uses loops, something like this:
def matrix(x):
for i in range(3):
matrix.append([])
for j in range(4):
matrix[i].append(0)
return matrix
You do not need to use explicit loops for something like this (unless you really want to). List comprehensions are a much more efficient way to generate lists, and have a similar syntax to a for loop:
Here is a comprehension for generating any MxN matrix containing the numbers up to M * N:
def matrix(m, n):
return [[x+1 for x in range(row * n, (row + 1) * n)] for row in range(m)]
Here is a comprehension for multiplying the nested list returned by matrix by some factor:
def mult(mat, fact):
return [[x * fact for x in row] for row in mat]
Here is the result for your specific 3x4 case:
>>> m = matrix(3, 4)
>>> print(m)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> m2 = mult(m, 2)
>>> print(m2)
[[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]
If you want the indices to be swapped as in your original example, just swap the inputs m and n:
>>> matrix(4, 3)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
mult will work the same for any nested list you pass in.