Summing up arrays without doubles - python

I would like to know if I have generated the 3 arrays in the manner below, how can I sum all the numbers up from all 3 arrys without summing up the ones that appear in each array.
(I would like to only som upt 10 once but I cant add array X_1 andX_2 because they both have 10 and 20, I only want to som up those numbers once.)
Maybe this can be done by creating a new array out of the X_1, X_2 and X_3 what leave out doubles?
def get_divisible_by_n(arr, n):
return arr[arr%n == 0]
x = np.arange(1,21)
X_1=get_divisible_by_n(x, 2)
#we get array([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20])
X_2=get_divisible_by_n(x, 5)
#we get array([ 5, 10, 15, 20])
X_3=get_divisible_by_n(x, 3)
#we get array([3, 6, 9, 12, 15, 18])

it is me again!
here is my solution using numpy, cuz i had more time this time:
import numpy as np
arr = np.arange(1,21)
divisable_by = lambda x: arr[np.where(arr % x == 0)]
n_2 = divisable_by(2)
n_3 = divisable_by(3)
n_5 = divisable_by(5)
what_u_want = np.unique( np.concatenate((n_2, n_3, n_5)) )
# [ 2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]

Not really efficient and not using numpy but here is one solution:
def get_divisible_by_n(arr, n):
return [i for i in arr if i % n == 0]
x = [i for i in range(21)]
X_1 = get_divisible_by_n(x, 2)
X_2 = get_divisible_by_n(x, 5)
X_3 = get_divisible_by_n(x, 3)
X_all = X_1+X_2+X_3
y = set(X_all)
print(sum(y)) # 142

Related

Checking if n elements in an array are increasing

I have written a code for SPC and I am attempting to highlight certain out of control runs.
So I was wondering if there was a way to pull out n(in my case 7) amount of increasing elements in an array so I can index with with the color red when I go to plot them.
This is what I attempted but I obviously get an indexing error.
import numpy as np
import matplotlib.pyplot as plt
y = np.linspace(0,10,15)
x = np.array([1,2,3,4,5,6,7,8,9,1,4,6,4,6,8])
col =[]
for i in range(len(x)):
if x[i]<x[i+1] and x[i+1]<x[i+2] and x[i+2]<x[i+3] and x[i+3]<x[i+4] and x[i+4]<x[i+5] and x[i+5]<x[i+6] and x[i+6]<x[i+7]:
col.append('red')
elif x[i]>x[i+1] and x[i+1]>x[i+2] and x[i+2]>x[i+3] and x[i+3]>x[i+4] and x[i+4]>x[i+5] and x[i+5]>x[i+6] and x[i+6]>x[i+7]:
col.append('red')
else:
col.append('blue')
for i in range(len(x)):
# plotting the corresponding x with y
# and respective color
plt.scatter(y[i], x[i], c = col[i], s = 10,
linewidth = 0)
Any help would be greatly appreciated!
As Andy said in his comment you get the index error because at i=8 you get to 15 which is the length of x.
Either you only loop over len(x)-7 and just repeat the last entry in col 7 times or you could do something like this:
import numpy as np
import matplotlib.pyplot as plt
y = np.linspace(0,10,20)
x = np.array([1,2,3,4,5,6,1,2,3,1,0,-1,-2,-3,-4,-5,-6,4,5])
col =[]
diff = np.diff(x) # get diff to see if x inc + or dec - // len(x)-1
diff_sign = np.diff(np.sign(diff)) # get difference of the signs to get either 1 (true) or 0 (false) // len(x)-2
zero_crossings = np.where(diff_sign)[0] + 2 # get indices (-2 from len(x)-2) where a zero crossing occures
diff_zero_crossings = np.diff(np.concatenate([[0],zero_crossings,[len(x)]])) # get how long the periods are till next zero crossing
for i in diff_zero_crossings:
if i >= 6:
for _ in range(i):
col.append("r")
else:
for _ in range(i):
col.append("b")
for i in range(len(x)):
# plotting the corresponding x with y
# and respective color
plt.scatter(y[i], x[i], c = col[i], s = 10,
linewidth = 0)
plt.show()
To determine if all integer elements of a list are ascending, you could do this:-
def ascending(arr):
_rv = True
for i in range(len(arr) - 1):
if arr[i + 1] <= arr[i]:
_rv = False
break
return _rv
a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 10, 11, 12, 13, 14, 16]
a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16]
print(ascending(a1))
print(ascending(a2))
If you want to limit the sequence of ascending values then you could just use nested loops. It may look inelegant but it's surprisingly efficient and much simpler than bringing dataframes into the mix:-
def ascending(arr, seq):
for i in range(len(arr) - seq + 1):
state = True
for j in range(i, i + seq - 1):
if arr[j] >= arr[j + 1]:
state = False
break
if state:
return True
return False
a1 = [100, 99, 98, 6, 7, 8, 10, 11, 12, 13, 14, 13]
a2 = [9, 8, 7, 6, 5, 4, 3, 2, 1]
print(ascending(a1, 7))
print(ascending(a2, 7))

PyTorch equivalent of numpy reshape function

Hi I have these to functions to flatten my complex type data to feed it to NN and reconstruct NN prediction to the original form.
def flatten_input64(Input): #convert (:,4,4,2) complex matrix to (:,64) real vector
Input1 = Input.reshape(-1, 32, order='F')
Input_vector=np.zeros([19957,64],dtype = np.float64)
Input_vector[:,0:32] = Input1.real
Input_vector[:,32:64] = Input1.imag
return Input_vector
def convert_output64(Output): #convert (:,64) real vector to (:,4,4,2) complex matrix
Output1 = Output[:,0:32] + 1j * Output[:,32:64]
output_matrix = Output1.reshape(-1, 4 ,4 ,2 , order = 'F')
return output_matrix
I am writing a customized loss that required all operation to be in torch and I should rewrite my conversion functions in PyTorch. The problem is that PyTorch doesn't have 'F' order reshape. I tried to write my own version of F reorder but, it doesn't work.
Do you have any idea what is my mistake?
def convert_output64_torch(input):
# number_of_samples = defined
for i in range(0, number_of_samples):
Output1 = input[i,0:32] + 1j * input[i,32:64]
Output2 = Output1.view(-1,4,4,2).permute(3,2,1,0)
if i == 0:
Output3 = Output2
else:
Output3 = torch.cat((Output3, Output2),0)
return Output3
Update: following #a_guest comment I tried to recreate my matrix with transpose and reshape and I got this code working same as F order reshape in numy:
def convert_output64_torch(input):
Output1 = input[:,0:32] + 1j * input[:,32:64]
shape = (-1 , 4 , 4 , 2)
Output3 = torch.transpose(torch.transpose(torch.reshape(torch.transpose(Output1,0,1),shape[::-1]),1,2),0,3)
return Output3
In both, Numpy and PyTorch, you can get the equivalent with the following operation: a.T.reshape(shape[::-1]).T (where a is either an array or a tensor):
>>> a = np.arange(16).reshape(4, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> shape = (2, 8)
>>> a.reshape(shape, order='F')
array([[ 0, 8, 1, 9, 2, 10, 3, 11],
[ 4, 12, 5, 13, 6, 14, 7, 15]])
>>> a.T.reshape(shape[::-1]).T
array([[ 0, 8, 1, 9, 2, 10, 3, 11],
[ 4, 12, 5, 13, 6, 14, 7, 15]])

Replacing chunks of elements in numpy array

I have an np.array like this one:
x = [1,2,3,4,5,6,7,8,9,10 ... N]. I need to replace the first n chunks with a certain element, like so:
for i in np.arange(0,125):
x[i] = x[0]
for i in np.arange(125,250):
x[i] = x[125]
for i in np.arange(250,375):
x[i] = x[250]
This is obviously not the way to go, but I just wrote it to this so I can show you what I need to achieve.
One way would be -
In [47]: x
Out[47]: array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
In [49]: n = 5
In [50]: x[::n][np.arange(len(x))//n]
Out[50]: array([10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20])
Another with np.repeat -
In [67]: np.repeat(x[::n], n)[:len(x)]
Out[67]: array([10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20])
For in-situ edit, we can reshape and assign in a broadcasted-manner, like so -
m = (len(x)-1)//n
x[:n*m].reshape(-1,n)[:] = x[:n*m:n,None]
x[n*m:] = x[n*m]
import numpy as np
x = np.arange(0,1000)
a = x[0]
b = x[125]
c = x[250]
x[0:125] = a
x[125:250] = b
x[250:375] = c
No need to write loops, you can replace bunch of values using slicing.
if the splits are equal, you can loop to calculate the stat and end positions instead of hard coding
To keep flexibility in the number of slice/value pairs you can write something like:
def chunk_replace(array, slice_list, value_list):
for s,v in zip(slice_list, value_list):
array[s] = v
return array
array = np.arange(1000)
slice_list = [slice(0,125), slice(125, 250), slice(250, 375)]
value_list = [array[0], array[125], array[250]]
result = chunk_replace(array, slice_list, value_list)

store two for loop output in a 2D matrix

I have a 3D matrix ‘DATA’ whose dimension is 100(L)X200(B)X50(H). The values are random for each grid point.
I want to the find the number of points where the values are between 10 and 20 in each vertical column. The output will be a 2D matrix.
For this I used the following code:
out = []
for i in range(np.shape(DATA)[0]):
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out.append(c)
but I am not getting the 2D matrix. Instead I am getting an array
Please Help
if you want to leverage numpy functionality:
import numpy as np
data = np.random.randint(0, 50, size=(100,200,50))
range_sum = np.sum(np.logical_and(np.less_equal(data, 20),
np.greater_equal(data, 10)
), axis=-1)
range_sum.shape
Out[6]: (100, 200)
range_sum
Out[7]:
array([[11, 12, 12, ..., 13, 9, 10],
[ 6, 12, 11, ..., 10, 14, 5],
[11, 11, 16, ..., 10, 12, 15],
...,
[11, 17, 9, ..., 12, 12, 11],
[ 9, 8, 10, ..., 7, 15, 12],
[12, 10, 11, ..., 12, 11, 19]])
You're using out as a list, and appending each value. Here's a quick modification to your code that should give you the desired result:
out = []
for i in range(np.shape(DATA)[0]):
out.append([]) # make a second dim for each i
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out[i].append(c)
The change is that I made out a list of lists. In each iteration over i, we append a new list. Then in the inner loop, we append values to the list at index i.
Update
If you want an numpy.ndarray instead, you can modify your code as follows:
import numpy as np
out = np.ndarray(np.shape(DATA)) # initialize to the desired shape
for i in range(np.shape(DATA)[0]):
for j in range(np.shape(DATA)[1]):
a = DATA[i,j,:]
b = a[(a>25) & (a<30)]
c = len(b)
out[i][j] = c

Python - how to add and subtract elements in array

If I have an array, let's say: np.array([4,8,-2,9,6,0,3,-6]) and I would like to add the previous number to the next element, how do I do?
And every time the number 0 shows up the addition of elements 'restarts'.
An example with the above array, I should get the following output when I run the function:
stock = np.array([4,12,10,19,25,0,3,-3]) is the right output, if the above array is inserted in transactions.
def cumulativeStock(transactions):
# insert your code here
return stock
I can't think of a method to solving this problem. Any help would be very appreciated.
I believe you mean something like this?
z = np.array([4,8,-2,9,6,0,3,-6])
n = z == 0
[False False False False False True False False]
res = np.split(z,np.where(n))
[array([ 4, 8, -2, 9, 6]), array([ 0, 3, -6])]
res_total = [np.cumsum(x) for x in res]
[array([ 4, 12, 10, 19, 25]), array([ 0, 3, -3])]
np.concatenate(res_total)
[ 4 12 10 19 25 0 3 -3]
another vectorized solution:
import numpy as np
stock = np.array([4, 8, -2, 9, 6, 0, 3, -6])
breaks = stock == 0
tmp = np.cumsum(stock)
brval = numpy.diff(numpy.concatenate(([0], -tmp[breaks])))
stock[breaks] = brval
np.cumsum(stock)
# array([ 4, 12, 10, 19, 25, 0, 3, -3])
import numpy as np
stock = np.array([4, 12, 10, 19, 25, 0, 3, -3, 4, 12, 10, 0, 19, 25, 0, 3, -3])
def cumsum_stock(stock):
## Detect all Zero's first
zero_p = np.where(stock==0)[0]
## Create empty array to append final result
final_stock = np.empty(shape=[0, len(zero_p)])
for i in range(len(zero_p)):
## First Zero detection
if(i==0):
stock_first_part = np.cumsum(stock[:zero_p[0]])
stock_after_zero_part = np.cumsum(stock[zero_p[0]:zero_p[i+1]])
final_stock = np.append(final_stock, stock_first_part)
final_stock = np.append(final_stock, stock_after_zero_part)
## Last Zero detection
elif(i==(len(zero_p)-1)):
stock_last_part = np.cumsum(stock[zero_p[i]:])
final_stock = np.append(final_stock, stock_last_part, axis=0)
## Intermediate Zero detection
else:
intermediate_stock = np.cumsum(stock[zero_p[i]:zero_p[i+1]])
final_stock = np.append(final_stock, intermediate_stock, axis=0)
return(final_stock)
final_stock = cumsum_stock(stock).astype(int)
#Output
final_stock
Out[]: array([ 4, 16, 26, ..., 0, 3, 0])
final_stock.tolist()
Out[]: [4, 16, 26, 45, 70, 0, 3, 0, 4, 16, 26, 0, 19, 44, 0, 3, 0]
def cumulativeStock(transactions):
def accum(x):
acc=0
for i in x:
if i==0:
acc=0
acc+=i
yield acc
stock = np.array(list(accum(transactions)))
return stock
for your input np.array([4,8,-2,9,6,0,3,-6])
it returns
array([ 1, 3, 6, 9, 13, 0, 1, 3, 6])
I assume you mean you want to seperate the list at every zero?
from itertools import groupby
import numpy
def cumulativeStock(transactions):
#split list on item 0
groupby(transactions, lambda x: x == 0)
all_lists = [list(group) for k, group in groupby(transactions, lambda x: x == 0) if not k]
# cumulative the items
stock = []
for sep_list in all_lists:
for item in numpy.cumsum(sep_list):
stock.append(item)
return stock
print(cumulativeStock([4,8,-2,9,6,0,3,-6]))
Which will return:
[4, 12, 10, 19, 25, 3, -3]

Categories

Resources