Is there a Python function that does what mapply do in R - python

Is there a function in Python that can do what Mapply do in R?
Basically I have a list of n inputs(each entry is a dataframe) for a function and corresponding lists(each list has the length of n) of parameters.
In each parameter lists, the position of each parameter corresponds to the respective position of input in the input list.
Now I wish to obtain the result in the exact order of the way I put my input, either in the form of a list with each element a dataframe(or matrix or whatever) or just one dataframe with all result appended. This is easily achievable in R using Mapply, but in python, I haven't got the luck to find any function that does the trick.
I haven't try this but one of the solution that i thought of is to pd.concat all lists(including input list and parameter lists) I got into one bulky list by column and apply the function to each row where I'll extract each element of the row to fill the function.
This might work but it would look quite stupid if there is actually one-line solution.
This is how I would deal with the problem in R:
result <- mapply(FUN = function(input, parameter1, parameter2) function_of_interest(input, parameter1, parameter2), input = input_list, parameter1 = parameter1_list, parameter2 = parameter2_list,... )

If I understand the question correctly, this example of mapply in R:
A <- c(1, 2, 3)
B <- c(2, 3, 4)
my_multiplication <- function(x,y){return(x*y)}
C <- mapply(my_multiplication, A, B)
could be roughly equivalent to this Python code:
a = [1, 2, 3]
b = [2, 3, 4]
def my_multiplication(x, y):
return x * y
c = map(my_multiplication, a, b)
The c is now a so called iterator. If I oversimplify, c can be viewed as a function that returns:
a[0] * b[0] on first call,
a[1] * b[1] on second call,
a[2] * b[2] on third (and last) call
i = 0
message = 'a[{}] * b[{}] = {} * {} = {}'
for result in c:
print(message.format(i, i ,a[i], b[i], result))
i += 1
prints
a[0] * b[0] = 1 * 2 = 2
a[1] * b[1] = 2 * 3 = 6
a[2] * b[2] = 3 * 4 = 12

My answer seems to be a modification of the answer given by #Paolo42, which just wraps the "map" function with a call to "list" to get rid of the loop:
>>> list(map(my_multiplication, A, B) )
[2, 6, 12]
I also liked the list comprehension solution given by #Alexander, but I also appreciate the comment from #Paolo42.

Related

About np.einsum

I don't understand how the following code realizes the transformation of dimensions? The shape of C is [2, 3, 3, 4]. How to realize the following matrix operation without einsum function?
import numpy as np
a = np.random.randint(0, 10, (2,3,4))
b = np.random.randint(0, 10, (3, 6, 4))
c = np.einsum('bld,hid-> blhd', a,b)
You can find more details in about einstein notation wikipedia
This means that you have indices b,l,h,i,d
this will iterate the indices to cover all the inputs and build the input
I will use capital letters for the arrays here to distinguish from the indices.
C[b,l,h,d] += A[b,l,d] * B[h,i,d]
The shape of the output can be determined as follows.
You take the index of each output axis and look for the same index in the input. For instance the first axis of C is indexed with b that is also used to index the first axis of A, thus assert C.shape[0] == A.shape[0]. Repeating for the other axes we have assert C.shape[1] == A.shape[1], assert C.shape[2] == B.shape[0], and assert C.shape[3] == A.shape[2], also assert C.shape[3] == B.shape[2].
Notice that the index i does not affect where the term will be added, each element of the output can be written as
C[b,l,h,d] = sum(A[b,l,d] * B[h,i,d] for i in range(B.shape[1]))
Notice also that i is not used to index A. So this could be also written as
C[b,l,h,d] = A[b,l,d] * B[h,:,d].sum();
Or if you want to use vectorized operation
first expanding then reducing
C = A[:,:,None,:] * B[None,None,:,:,:].sum(-2)
expanding reducing then expandin, possible because A does not use i
C = A[:,:,None,:] * B.sum(-2)[None,None,:,:]
To answer your first question
c = np.einsum('bld,hid->blhd', a,b)
implements the formula
which, if you don't want to use einsum, you can achieve using
c = a[:, :, None, :] * b.sum(-2)[None, None, :, :]
# b l (h) d i (b) (l) h d

Elegant and/or fast equivalents of Excel SUMXMY2 (sum of square of differences of corresponding array elements) in python

Test Sample:
a = [0.1357678 0.27303184 -0.75600229]
b = [0.3813097 -0.72613616 0.18361217]
I would like to implement SUMXMY2(a, b) in Python without for loops
How can I do this?
As far as I know, - is not a valid operator for lists, so I would use a list comprehension. It does technically use a for loop, however I'd call it "elegant enough".
c = [(b[i] - a[i]) ** 2 for i in range(len(b))]
result = sum(c)
To make it more compact but less readable:
c = sum([(b[i] - a[i]) ** 2 for i in range(len(b))])
If you're dealing with lists of different lengths, use this:
c = [(b[i] - a[i]) ** 2 for i in range(min(len(b), len(a)))]
result = sum(c)
Squared difference is given by:
c = ((a - b) ** 2)
The sum is then simply given by
c = c.sum()
if a and b are lists you can convert them to pandas series first:
a = pd.Series(a)
or to numpy array as:
a = np.asarray(a)

python lists: merge and replace

I am looking for a more elegant/Pythonic way of doing the following task:
I have two string lists A and B, where B is almost a subset of A except that B has a postfix * for some of the elements. My goal is to replace elements in A with those corresponding elements in B that have the postfix. An example:
A = ['abcd', 'ddse', '123d', 'aaaaa']
B = ['ddse', 'aaaaa*']
I'd like to get a list as ['abcd', 'ddse', '123d', 'aaaaa*']. The way I can think of is to split and transform A in to a two-column dataframe and merge with B, then put the * column back to column in B. But that does not look very elegant since I need to do a lot of this operation. Is there a better way of doing it?
Thanks!
If the * is always at the end, it's pretty simple with this code:
C = [(x + '*') if ((x + '*') in B) else x for x in A]
To do the same thing for a list of lists, try this; you will get the results in a list of lists C then:
C = []
for A, B in zip(A_L, B_L):
C.append([x + '*' if ((x + '*') in B) else x for x in A])
What about this?:
def doit(A,B):
for n,i in enumerate(A):
if i + '*' in B:
A[n] = i + '*'
This?
[ e+'*' if e+'*' in B else e for e in A]
So you really want to check, for every element a of A, whether there is some element a* of B, and if there is some a*, to replace a in A with a*.
#make a copy of A with * appended to every element
C = [a + "*" for a in A]
#loop through C and check
for i in range(len(A)):
if C[i] in B:
A[i] = C[i]

Convert this function from recursive to iterative

def g(n):
"""Return the value of G(n), computed recursively.
>>> g(1)
1
>>> g(2)
2
>>> g(3)
3
>>> g(4)
10
>>> g(5)
22
"""
if n<=3:
return n
else:
return g(n-1)+2*g(n-2)+3*g(n-3)
How do I convert this to an iterative function? Until now, I didn't realize that writing a recursive function is sometimes easier than writing an iterative one. The reason why it's so hard I think is because I don't know what operation the function is doing. In the recursive one, it's not obvious what's going on.
I want to write an iterative definition, and I know I need to use a while loop, but each time I try to write one either I add additional parameters to g_iter(n) (when there should only be one), or I make a recursive call. Can someone at least start me off on the right path? You don't have to give me a complete solution.
FYI: We have not learned of the all too common "stack" I'm seeing on all these pages. I would prefer to stay away from this.
def g_iter(n):
"""Return the value of G(n), computed iteratively.
>>> g_iter(1)
1
>>> g_iter(2)
2
>>> g_iter(3)
3
>>> g_iter(4)
10
>>> g_iter(5)
22
"""
"*** YOUR CODE HERE ***"
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
for i in range(n - 3):
a, b, c = b, c, c + 2 * b + 3 * a
return c
UPDATE response to comment, without using for loop.
def g(n):
if n <= 3:
return n
a, b, c = 1, 2, 3
while n > 3:
a, b, c = b, c, c + 2 * b + 3 * a
n -= 1
return c

What is a subtraction function that is similar to sum() for subtracting items in list?

I am trying to create a calculator, but I am having trouble writing a function that will subtract numbers from a list.
For example:
class Calculator(object):
def __init__(self, args):
self.args = args
def subtract_numbers(self, *args):
return ***here is where I need the subtraction function to be****
For addition, I can simply use return sum(args) to calculate the total but I am unsure of what I can do for subtractions.
from functools import reduce # omit on Python 2
import operator
a = [1,2,3,4]
xsum = reduce(operator.__add__, a) # or operator.add
xdif = reduce(operator.__sub__, a) # or operator.sub
print(xsum, xdif)
## 10 -8
reduce(operator.xxx, list) basically "inserts" the operator in-between list elements.
It depends exactly what you mean. You could simply subtract the sum of the rest of the numbers from the first one, like this:
def diffr(items):
return items[0] - sum(items[1:])
It's tough to tell because in subtraction it's dependent on the order in which you subtract; however if you subtract from left to right, as in the standard order of operations:
x0 - x1 - x2 - x3 - ... - xn = x0 - (x1 + x2 + x3 + ... + xn)
which is the same interpretation as the code snippet defining diffr() above.
It seems like maybe in the context of your calculator, x0 might be your running total, while the args parameter might represent the numbers x1 through xn. In that case you'd simply subtract sum(args) from your running total. Maybe I'm reading too much into your code... I think you get it, huh?
Subtract function is same as sum having negative signs like this
x = 1
y = 2
sum([x, y])
>>> 3
sum([x, -y])
>>> -1
for more numbers
a = 5
b = 10
c = 15
sum([a, b, c])
sum([a, -b, -c])
In general,
Subtract function is formed by changing you list signs like this
l = [1, 2, 3, 4, ...., n]
new_l = l[0] + [-x for x in l[1:]
# Or
new_l = [-x for x in l]
new_l[0] = -newl[0]
# Or one liner,
new_l = [-x for x in l if x != l[0]]

Categories