Subtracting columns from a numpy array - python

This question is a follow-up of a previous post of mine:
Multiply each column of a numpy array with each value of another array.
Suppose i have the following arrays:
In [252]: k
Out[252]:
array([[200, 800, 400, 1600],
[400, 1000, 800, 2000],
[600, 1200, 1200,2400]])
In [271]: f = np.array([[100,50],[200,100],[300,200]])
In [272]: f
Out[272]:
array([[100, 50],
[200, 100],
[300, 200]])
How can i subtract f from k to obtain the following?
In [252]: g
Out[252]:
array([[100, 750, 300, 1550],
[200, 900, 600, 1900],
[300, 1000, 900,2200]])
Ideally, i would like to make the subtraction in as fewer steps as possible and in concert with the solution provided in my other post, but any solution welcome.

You can use np.tile, like this:
In [1]: k - np.tile(f, (1, 2))
Out[1]:
array([[ 100, 750, 300, 1550],
[ 200, 900, 600, 1900],
[ 300, 1000, 900, 2200]])
Also, if you happen to know for sure that each dimension of f evenly divides the corresponding dimension of k (which I assume you must, for your desired subtraction to make sense), then you could generalize it slightly:
In [2]: k - np.tile(f, np.array(k.shape) // np.array(f.shape))
Out[2]:
array([[ 100, 750, 300, 1550],
[ 200, 900, 600, 1900],
[ 300, 1000, 900, 2200]])

You can reshape k, to fit f in two dimensions, and use broadcasting:
>>> g = (k.reshape(f.shape[0], -1, f.shape[1]) - f[:, None, :]).reshape(k.shape)
array([[ 100, 750, 300, 1550],
[ 200, 900, 600, 1900],
[ 300, 1000, 900, 2200]])

Related

How to add Element to a List in Python inside another list

I'm trying to add "7000" element to this list [10, 20, [300, 400, [5000, 6000, ], 500], 30, 40]
I want to add 7000 after 6000 on this list … already try some methods to add this element
Use the append() method to update an list in place
>>> x = [10, 20, [300, 400, [5000, 6000], 500], 30, 40]
>>> x[2][2].append(7000)
>>> x
[10, 20, [300, 400, [5000, 6000, 7000], 500], 30, 40]
You can use the append() method on any list, no matter how nested it is.
your list:- lst=[10, 20, [300, 400, [5000, 6000, ], 500], 30, 40]
well see in your list at index position 2 there is another list
that list:-[300, 400, [5000, 6000, ], 500]
in the above list there is another list at index 2 i.e [5000, 6000, ]
so use append() method in this code:-
lst[2][2].append(7000)

How can i multiply each element in a python list with element in another list?

x = [5,10,15,20,25,30]
y = [60,90,120,150,190,200]
I want to multiply 5x60 , 10x90 , 15x120 , 20x150 , 25x190 , 30x200
and store them in z=[]
how can I do it ? thanks
I have tried this but it multiplies each element with all the element in x with all element in y
***x = [5,10,15,20,25,30]
y = [60,90,120,150,190,200]
sumx= sum(x)
sumy=sum(y)
for i in x:
z=[i* j for j in y]
print(z)***
result for this
[300, 450, 600, 750, 950, 1000]
[600, 900, 1200, 1500, 1900, 2000]
[900, 1350, 1800, 2250, 2850, 3000]
[1200, 1800, 2400, 3000, 3800, 4000]
[1500, 2250, 3000, 3750, 4750, 5000]
[1800, 2700, 3600, 4500, 5700, 6000]
You can do this:
ans = [i*j for i, j in zip(x, y)]
gives
[300, 900, 1800, 3000, 4750, 6000]
If you're planning on doing a lot of arithmetic with arrays, you might want to consider using numpy.
import numpy as np
x = np.array([5,10,15,20,25,30])
y = np.array([60,90,120,150,190,200])
result = x * y
If this is a one-time thing only, then #Jarvis's solution is absolutely the right answer.
Found this to work:
x = [5,10,15,20,25,30]
y = [60,90,120,150,190,200]
a = 0
z = []
for i in range(len(x)):
z.append(x[a] * y[a])
a += 1
print(z)
Got this as an output:
[300, 900, 1800, 3000, 4750, 6000]

NumPy replace values with arrays based on conditions

I am trying to produce a sorter that, for each weekly total (for multiple different products), places them in the right buckets based on the max cumulative allowable less what has already been sorted.
maxes=np.array([100,200,300],[100,400,900])
weeklytotals=np.array([100,150,200,250],[200,400,600,800)]
The desired output would be:
result=np.array([[100,0,0],[100,50,0],[100,100,0],[100,150,0]],[[100,100,0],[100,300,0],[100,400,100],[100,400,300]]
I do not want to use loops but I am racking my mind on how to avoid that method. Thanks in advance, still a Python beginner. I want to use NumPy because the end implementation will need to be extremely fast.
One vectorized approach could be:
result = np.minimum(weeklytotals[:,:,None], maxes.cumsum(1)[:,None,:])
result[...,1:] -= result[...,:-1]
result
#array([[[100, 0, 0],
# [100, 50, 0],
# [100, 100, 0],
# [100, 150, 0]],
# [[100, 100, 0],
# [100, 300, 0],
# [100, 400, 100],
# [100, 400, 300]]])
Firstly calculate the cumulative capacity for the buckets:
maxes.cumsum(1)
#array([[ 100, 300, 600],
# [ 100, 500, 1400]])
calculate the cumulative amount in the buckets by taking the minimum between weekly total and capacity:
result = np.minimum(weeklytotals[:,:,None], maxes.cumsum(1)[:,None,:])
#array([[[100, 100, 100],
# [100, 150, 150],
# [100, 200, 200],
# [100, 250, 250]],
# [[100, 200, 200],
# [100, 400, 400],
# [100, 500, 600],
# [100, 500, 800]]])
Take the difference of amounts between buckets and assign them back (except for the first bucket):
result[...,1:] -= result[...,:-1]
result

Checking for overlap between time spans

I have a list of time entries (HHMM format) with a start time and a stop. I'm having trouble figuring out how to code it in Python where it returns if there's an overlap or not in the list.
Example
Entry 1: 1030, 1245;
Entry 2: 1115, 1300
== True
Entry 1: 0900, 1030;
Entry 2: 1215, 1400
== False
First we sort the list by the start time.
Then we loop over it checking if the next start time is lower then the previous end time.
This will check if x+1 overlaps with x (not if x+2 overlaps with x, etc.)
intervals = [[100,200],[150,250],[300,400]]
intervalsSorted = sorted(intervals, key=lambda x: x[0]) # sort by start time
for x in range(1,len(intervalsSorted)):
if intervalsSorted[x-1][1] > intervalsSorted[x][0]:
print "{0} overlaps with {1}".format( intervals[x-1], intervals[x] )
# result: [100, 200] overlaps with [150, 250]
The following should give you all overlappings in the whole list.
intervals = [[100,200],[150,250],[300,400],[250,500]]
overlapping = [ [x,y] for x in intervals for y in intervals if x is not y and x[1]>y[0] and x[0]<y[0] ]
for x in overlapping:
print '{0} overlaps with {1}'.format(x[0],x[1])
# results:
# [100, 200] overlaps with [150, 250]
# [250, 500] overlaps with [300, 400]
Note that this is a O(n*n) lookup. (anyone correct me here if I'm wrong!)
This is likely slower than the first (didn't test it, but I assume it is) because this iterates over the whole list for each single index. Should be similar to arbarnert's nested for loops example. But then again this does give you all the overlapping values as opposed to the first method I showed that only checked for overlapping times between those next to it (sorted by start time).
Extended test gives:
intervals = [[100,200],[150,250],[300,400],[250,500],[10,900],[1000,12300],[-151,32131],["a","c"],["b","d"],["foo","kung"]]
overlapping = [ [x,y] for x in intervals for y in intervals if x is not y and x[1]>y[0] and x[0]<y[0] ]
for x in overlapping:
print '{0} overlaps with {1}'.format(x[0],x[1])
# results:
# [100, 200] overlaps with [150, 250]
# [250, 500] overlaps with [300, 400]
# [10, 900] overlaps with [100, 200]
# [10, 900] overlaps with [150, 250]
# [10, 900] overlaps with [300, 400]
# [10, 900] overlaps with [250, 500]
# [-151, 32131] overlaps with [100, 200]
# [-151, 32131] overlaps with [150, 250]
# [-151, 32131] overlaps with [300, 400]
# [-151, 32131] overlaps with [250, 500]
# [-151, 32131] overlaps with [10, 900]
# [-151, 32131] overlaps with [1000, 12300]
# ['a', 'c'] overlaps with ['b', 'd']
For future reference, the solution of #Roy doesn't work for intervals that have the same end or start times. The following solution does:
intervals = [[100, 200], [150, 250], [300, 400], [250, 500], [100, 150], [175, 250]]
intervals.sort()
l = len(intervals)
overlaps = []
for i in xrange(l):
for j in xrange(i+1, l):
x = intervals[i]
y = intervals[j]
if x[0] == y[0]:
overlaps.append([x, y])
elif x[1] == y[1]:
overlaps.append([x, y])
elif (x[1]>y[0] and x[0]<y[0]):
overlaps.append([x, y])
Also, an Interval Tree could be used for these kinds of problems.
To expand on #Roy's answer to include situations where something has the same time slot and you need to distinguish:
intervals = [[100,200, "math"],[100,200, "calc"], [150,250, "eng"],[300,400, "design"],[250,500, "lit"],[10,900, "english"],[1000,12300, "prog"],[-151,32131, "hist"]]
overlapping = [ [x,y] for x in intervals for y in intervals if x is not y and x[1]>y[0] and x[0]<y[0] or x[0]==y[0] and x[1]==y[1] and x is not y]
for x in overlapping:
print '{0} overlaps with {1}'.format(x[0],x[1])
# Prints
#[100, 200, 'math'] overlaps with [100, 200, 'calc']
#[100, 200, 'math'] overlaps with [150, 250, 'eng']
#[100, 200, 'calc'] overlaps with [100, 200, 'math']
#[100, 200, 'calc'] overlaps with [150, 250, 'eng']
#[250, 500, 'lit'] overlaps with [300, 400, 'design']
#[10, 900, 'english'] overlaps with [100, 200, 'math']
#[10, 900, 'english'] overlaps with [100, 200, 'calc']
#[10, 900, 'english'] overlaps with [150, 250, 'eng']
#[10, 900, 'english'] overlaps with [300, 400, 'design']
#[10, 900, 'english'] overlaps with [250, 500, 'lit']
#[-151, 32131, 'hist'] overlaps with [100, 200, 'math']
#[-151, 32131, 'hist'] overlaps with [100, 200, 'calc']
#[-151, 32131, 'hist'] overlaps with [150, 250, 'eng']
#[-151, 32131, 'hist'] overlaps with [300, 400, 'design']
#[-151, 32131, 'hist'] overlaps with [250, 500, 'lit']
#[-151, 32131, 'hist'] overlaps with [10, 900, 'english']
#[-151, 32131, 'hist'] overlaps with [1000, 12300, 'prog']
Assuming you have an intervals_overlap(interval1, interval2) function…
The first idea is a naive iteration over every pair of intervals in the list:
for interval1 in intervals:
for interval2 in intervals:
if interval1 is not interval2:
if intervals_overlap(interval1, interval2):
return True
return False
But you should be able to figure out smarter ways of dong this.
Simple way to do it:
I change the number into string since entry 3 contains 0900, which is invalid.
entry01 = ('1030', '1245')
entry02 = ('1115', '1300')
entry03 = ('0900', '1030')
entry04 = ('1215', '1400')
def check(entry01, entry02):
import itertools
input_time_series = list(itertools.chain.from_iterable([entry01, entry02]))
if input_time_series != sorted(input_time_series):
return False
return True
>>> check(entry01, entry02)
False
>>> check(entry03, entry04)
True

How to raise an array in power while broadcasting it?

i have to following problem: I need a 1d-string with equaly distributed numbers on a LOG-scale. To eb precise: 1,2,3,4,5,6,7,8,9,10,20,30,40...,100,200,300,... and so on. This can go up to 10^9, so typing is not an option ;)
my code so far is the following:
ome = np.linspace(1,9,9).reshape(9,1)
pow = np.linspce(0,5,6).reshape(1,6)
logome = ome*(10**pow)
but this not working and i don't know how to proceed... any suggestions?
okay, i figured some way out, if anybody is interested:
ome = np.linspace(1,9,9).reshape(1,9)
pow = np.linspce(0,5,6)
pow = np.power(10,pow).reshape(6,1)
logome = ome*pow
logome.reshape(54)
et voila :)
To get your desired output, I'd probably do something like this:
>>> (np.arange(1, 10) * 10**np.arange(9)[:,None]).flatten()
array([ 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 20, 30,
40, 50, 60, 70, 80, 90,
100, 200, 300, 400, 500, 600,
700, 800, 900, 1000, 2000, 3000,
4000, 5000, 6000, 7000, 8000, 9000,
10000, 20000, 30000, 40000, 50000, 60000,
70000, 80000, 90000, 100000, 200000, 300000,
400000, 500000, 600000, 700000, 800000, 900000,
1000000, 2000000, 3000000, 4000000, 5000000, 6000000,
7000000, 8000000, 9000000, 10000000, 20000000, 30000000,
40000000, 50000000, 60000000, 70000000, 80000000, 90000000,
100000000, 200000000, 300000000, 400000000, 500000000, 600000000,
700000000, 800000000, 900000000])
where the second term works like this:
>>> np.arange(5)
array([0, 1, 2, 3, 4])
>>> np.arange(5)[:, None]
array([[0],
[1],
[2],
[3],
[4]])
>>> 10**np.arange(5)[:, None]
array([[ 1],
[ 10],
[ 100],
[ 1000],
[10000]])
You might also be interested in np.logspace. BTW, note that this array isn't equally distributed on a log-scale.

Categories