Multiply two arrays with different dimensions using numpy - python

I need a faster/optimised version of my current code:
import numpy as np
a = np.array((1, 2, 3))
b = np.array((10, 20, 30, 40, 50, 60, 70, 80))
print([i*b for i in a])
Is there any faster way to do this using numpy functions (maybe without reshaping and blowing up the whole thing)?

Looks like the outer product.
>>> np.outer(a, b)
array([[ 10, 20, 30, 40, 50, 60, 70, 80],
[ 20, 40, 60, 80, 100, 120, 140, 160],
[ 30, 60, 90, 120, 150, 180, 210, 240]])

Related

Combination sum higher than and lower than

im now starting in programing. I get one exercise to generate a combination of 10 numbers with a set of numbers, and make a sum and the sum of that numbers need to be less than 800 and higher than 700, and print the result and combination (Print All combinations).
For example if the set of numbers is 10,20,30,40,50,60,70,80,90,100 and i need to generate a set of 10 numbers using the numbers i set and the sum of that combination need to be less 560 and higher than 500.
10+20+30+40+50+60+70+80+90+100 = 550
10+20+30+40+50+40+100+80+90+90 = 550
..
I start a code in Python, but im little stuck, how i can sum the combinations.
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
print(combinations)
sum(e for e in combinations if e >= 550)
You're very close, but you need to filter based on whether sum(e) is in the desired range, not whether e itself is.
>>> from itertools import combinations
>>> myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> [e for i in range(len(myList)) for e in combinations(myList, i) if 500 < sum(e) < 560]
[(20, 40, 50, 60, 70, 80, 90, 100), (30, 40, 50, 60, 70, 80, 90, 100), (10, 20, 30, 50, 60, 70, 80, 90, 100), (10, 20, 40, 50, 60, 70, 80, 90, 100), (10, 30, 40, 50, 60, 70, 80, 90, 100), (20, 30, 40, 50, 60, 70, 80, 90, 100)]
combinations only exists inside your inner for loop - you can sum it right after you print it simply with sum(combinations). Your sum() statement is outside the loop, where combinations is no longer defined.
Something like:
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
if 500 < sum(combinations) < 560:
print(combinations, sum(combinations))

How to convert numeric to strings in the box plot

I want to plot the boxplot of the following dataset :
A = [150, 112, 108, 70]
B = [260, 90, 165, 100]
C = [160, 50, 90, 60]
D = [110, 20, 35, 70]
E = [105, 450, 45, 200]
One way I can do it is via the following code:
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
font_prop = font_manager.FontProperties( size=18)
Positions = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5]
Heat = [150, 112, 108, 70, 260, 90, 165, 100, 160, 50, 90, 60, 110, 20, 35, 70, 105, 450, 45, 200]
groups = [[] for i in range(max(Positions))]
[groups[Positions[i]-1].append(Heat[i]) for i in range(len(Heat))];
b = plt.boxplot(groups, patch_artist=False);
plt.rcParams.update({'font.size': 16})
plt.rc ('xtick', labelsize=16)
plt.rc ('ytick', labelsize=18)
for median in b['medians']:
median.set(color = 'r', linewidth = 2)
I can get the following box plot but I want the numbers 1...5 to be replaced by A...E? Is there an alternative way I can do this?
To convert a char to an integer, use
ord(char)
To convert an integer to a char, use
chr(int)
An example:
int_array = list(range(5))
char_array = [chr(x + ord('A')) for x in int_array]
# char_array = ['A', 'B', 'C', 'D', 'E']

Use Numpy polyadd() to add two polynomials

I'm trying to add two polynomials using Numpy's polyadd(), but i'm getting the wrong result
a = [60, 51, 64, 38, 9, 79, 96, 81, 11]
e = [1,0,1,0,1,0,1]
b = np.polyadd(a, e)
b
array([60, 51, 65, 38, 10, 79, 97, 81, 12])
Is there an easy way to get the correct result (61, 51, 65, 38, 10, 79, 97, 81, 11) ?
Numpy treats coefficients from lowest to the highest order right? So here it should be (60+51x+64x^2+38x^3+9x^4+79x^5+96x^6+81x^7+11x^8)+(1+x^2+x^4+x^6) = 61+51x+65x^2+38x^3+10x^4+79x^5+97x^6+81x^7+11x^8
You are seeing the docs for different function. np.polynomial.polynomial.polyadd uses from lowest order to highest from left to right, whereas, np.polyadd ranks from highest to lowest.
>>> a = [60, 51, 64, 38, 9, 79, 96, 81, 11]
>>> e = [1,0,1,0,1,0,1]
>>> np.polyadd(a, e)
array([60, 51, 65, 38, 10, 79, 97, 81, 12])
>>> np.polynomial.polynomial.polyadd(a,e)
array([61., 51., 65., 38., 10., 79., 97., 81., 11.])
The result you are asking for can be obtained using np.polyadd by reversing the lists and then reversing the obtained result as suggested by #Mad Physicist:
>>> np.polyadd(a[::-1], e[::-1])[::-1]
array([61, 51, 65, 38, 10, 79, 97, 81, 11])

Bubble sort not sorting properly in python

I'm making bubble sort in Python but have no idea why it doesn't sort properly.
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[i] > N[i+1]):
N[i], N[i+1] = N[i+1], N[i]
print(N)
This is result of this code
[20, 40, 50, 10000, 50, 60, 90, 100, 5000, 22, 80000]
You should compare N[j] with N[j+1], because you need repeatedly swapping the adjacent elements if they are in wrong order.
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[j] > N[j+1]):
N[j], N[j+1] = N[j+1], N[j]
print(N)
Output
[20, 22, 40, 50, 50, 60, 90, 100, 5000, 10000, 80000]
You should use 'j' instead of 'i' in the body of the second loop. Otherwise it is pointless to have both loops. Only the outer loop is effectively executed.
I believe you mixed up your indices i and j. It should read:
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[j] > N[j+1]):
N[j], N[j+1] = N[j+1], N[j]
print(N)
Output:
[20, 22, 40, 50, 50, 60, 90, 100, 5000, 10000, 80000]

Merge equally sized arrays into tiled big array

I'm having a hard time phrasing what I want, which is why I didn't find it on Google. Let me start with an example before formulating the general case.
Say we have 7 arrays a1, ..., a7, each of shape (4, 5). I want a new array where the 7 arrays are arranged like this:
a1 a2 a3
a4 a5 a6
a7 0 0
This array is of shape (3*4, 3*5) == (12, 15), 0 is np.zeros((4, 5)).
In general, I have C arrays a1, ..., aC, of shape (H, W), and I want to put them into an array of shape (h*H, w*W), where h = ceil(sqrt(C)) and w = ceil(C/h). The C arrays are stored as one (C, H, W) dimensional array.
What's the most elegant way to do this? I was hacking something together by iterating over the necessary indices but it's not nice so I stopped.
Speed is not top priority and the arrays are fairly small.
Approach #1
Some permuting of axes and reshaping should do the job -
C,m,n = a.shape
h = int(np.ceil(np.sqrt(C)))
w = int(np.ceil(C/h))
out = np.zeros((h,w,m,n),dtype=a.dtype)
out.reshape(-1,m,n)[:C] = a
out = out.swapaxes(1,2).reshape(-1,w*n)
Sample input, output -
In [340]: a
Out[340]:
array([[[55, 58],
[75, 78]],
[[78, 20],
[94, 32]],
[[47, 98],
[81, 23]],
[[69, 76],
[50, 98]],
[[57, 92],
[48, 36]],
[[88, 83],
[20, 31]],
[[91, 80],
[90, 58]]])
In [341]: out
Out[341]:
array([[55, 58, 78, 20, 47, 98],
[75, 78, 94, 32, 81, 23],
[69, 76, 57, 92, 88, 83],
[50, 98, 48, 36, 20, 31],
[91, 80, 0, 0, 0, 0],
[90, 58, 0, 0, 0, 0]])
Approach #2
Simpler one with zeros-concatenation -
z = np.zeros((h*w-C,m,n),dtype=a.dtype)
out = np.concatenate((a,z)).reshape(h,w,m,n).swapaxes(1,2).reshape(-1,w*n)
That could be modified/simplified a bit by using zeros-padding with np.pad -
zp = np.pad(a,((0,h*w-C),(0,0),(0,0)),'constant')
out = zp.reshape(h,w,m,n).swapaxes(1,2).reshape(-1,w*n)

Categories

Resources