Problems with the zip function: lists that seem not iterable - python

I'm having some troubles trying to use four lists with the zip function.
In particular, I'm getting the following error at line 36:
TypeError: zip argument #3 must support iteration
I've already read that it happens with not iterable objects, but I'm using it on two lists! And if I try use the zip only on the first 2 lists it works perfectly: I have problems only with the last two.
Someone has ideas on how to solve that? Many thanks!
import numpy
#setting initial values
R = 330
C = 0.1
f_T = 1/(2*numpy.pi*R*C)
w_T = 2*numpy.pi*f_T
n = 10
T = 1
w = (2*numpy.pi)/T
t = numpy.linspace(-2, 2, 100)
#making the lists c_k, w_k, a_k, phi_k
c_karray = []
w_karray = []
A_karray = []
phi_karray = []
#populating the lists
for k in range(1, n, 2):
c_k = 2/(k*numpy.pi)
w_k = k*w
A_k = 1/(numpy.sqrt(1+(w_k)**2))
phi_k = numpy.arctan(-w_k)
c_karray.append(c_k)
w_karray.append(w_k)
A_karray.append(A_k)
phi_karray.append(phi_k)
#making the function w(t)
w = []
#doing the sum for each t and populate w(t)
for i in t:
w_i = ([(A_k*c_k*numpy.sin(w_k*i+phi_k)) for c_k, w_k, A_k, phi_k in zip(c_karray, w_karray, A_k, phi_k)])
w.append(sum(w_i)

Probably you mistyped the last 2 elements in zip. They should be A_karray and phi_karray, because phi_k and A_k are single values.
My result for w is:
[-0.11741034896740517,
-0.099189027720991918,
-0.073206290274556718,
...
-0.089754003567358978,
-0.10828235682188027,
-0.1174103489674052]
HTH,
Germán.

I believe you want zip(c_karray, w_karray, A_karray, phi_karray). Additionally, you should produce this once, not each iteration of the for the loop.
Furthermore, you are not really making use of numpy. Try this instead of your loops.
d = numpy.arange(1, n, 2)
c_karray = 2/(d*numpy.pi)
w_karray = d*w
A_karray = 1/(numpy.sqrt(1+(w_karray)**2))
phi_karray = numpy.arctan(-w_karray)
w = (A_karray*c_karray*numpy.sin(w_karray*t[:,None]+phi_karray)).sum(axis=-1)

Related

Numpy is not swapping elements

I am trying to swap two indices in the 2D array of NumPy. Unfortunately, only one element is getting swapped. Here is the code:
n = len(A)
perMatrix = np.zeros((n,n))
np.fill_diagonal(perMatrix, 1)
perMatrix = A
# swapping the row
print(perMatrix)
temp = perMatrix[switchIndex1]
print(temp)
# perMatrix[switchIndex1][0] = 14
perMatrix[switchIndex1], perMatrix[switchIndex2] = perMatrix[switchIndex2], perMatrix[switchIndex1]
print(perMatrix)
Here's what the code is outputting:
You could just add (on the line after perMatrix is created):
sigma = [switchIndex1, switchIndex2]
tau = [switchIndex2, switchIndex1]
perMatrix[sigma,:] = perMatrix[tau,:]

Creating multiple matrices with nested loop using numpy

import numpy as np
import random
x = np.linspace(-3.0,3.0,25)
b = 3; a = -3; n = 24
N = np.matrix(np.zeros(shape=(4,24)));
G = [] #want to save the 2 4by 24 matrices in G
s = []; g = []
Y = []
random.seed(4)
for j in range(0,2):
Y.append(np.random.randint(-6.0,6.0,size=(4,1)))
h = (b-a)/float(n)
s.append(0.5*h*((1+(np.cos((np.pi*(a-Y[j]))/3.0)))))
g.append(0.5*h*(1+(np.cos((np.pi*(b-Y[j]))/3.0))))
for k in range(0,Y[j].shape[0]):
for l in range(1, x.shape[0]-1):
N[k,l] = h*(1 + (np.cos((np.pi*(x[l]-Y[j][k]))/3.0)))
N[k,0] = s[j][k]
N = np.concatenate((N,g[j]),axis=1)
print(N)
Please, I need help. When I run this code, it produces just a single 4by25 matrix but it is suppose to be 2 4by25 matrix. I dont know why. My goal is to have the 2 4by25 matrices stored to variable G so that when i call G[0], it produces the first 4by25 and G[1] produces the second 4by25. Here Y outputs 2 4by1 coulmn vectors.
How is your code supposed to append 2 matrices to G? You are totally missing that part.
I don't really get what values you're looking for, so I can't tell you if values are added correctly, anyway you should add this line:
G.append(N)
(I'm just assuming you are appending N because it is the only 2x24 matrix)
Before the end of the first cylce, result should be something like:
for j in range(0,2):
Y.append(np.random.randint(-6.0,6.0,size=(4,1)))
h = (b-a)/float(n)
s.append(0.5*h*((1+(np.cos((np.pi*(a-Y[j]))/3.0)))))
g.append(0.5*h*(1+(np.cos((np.pi*(b-Y[j]))/3.0))))
for k in range(0,Y[j].shape[0]):
for l in range(1, x.shape[0]-1):
N[k,l] = h*(1 + (np.cos((np.pi*(x[l]-Y[j][k]))/3.0)))
N[k,0] = s[j][k]
N = np.concatenate((N,g[j]),axis=1)
G.append(N)

Sum total by two conditions in list of lists

cust_id = semi_final_df['0_x'].tolist()
date = semi_final_df[1].tolist()
total_amount = semi_final_df[0].tolist()
prod_num = semi_final_df['0_y'].tolist()
prod_deduped = []
quant_cleaned = []
product_net_amount = []
cust_id_final = []
date_final = []
for row in total_amount:
quant_cleaned.append(float(row))
for unique_prodz in prod_num:
if unique_prodz not in prod_deduped:
prod_deduped.append(unique_prodz)
for unique_product in prod_deduped:
indices = [i for i, x in enumerate(prod_num) if x == unique_product]
product_total = 0
for index in indices:
product_total += quant_cleaned[index]
product_net_amount.append(product_total)
first_index = prod_num.index(unique_product)
cust_id_final.append(cust_id[first_index])
date_final.append(date[first_index])
Above code calculates sum amount by one condition in order to sum the total on an invoice.
The data had multiple lines but shared the same invoice/product number.
Problem:
I need to modify the below code so that I can sum by unique product and unique date.
I have given it a go but I am getting a value error -
saying x, y is not in a list
As per my understanding the issue lies in the fact that I am zipping two de-duped lists together of different lengths and then I am attempting to loop through the result inline.
This line causes the error
for i,[x, y] in enumerate(zipped_list):
Any help would be sincerely appreciated. Here is the second batch of code with comments.
from itertools import zip_longest
#I have not included the code for the three lists below but you can assume they are populated as these are the lists that I will be #working off of. They are of the same length.
prod_numbers = []
datesz = []
converted_quant = []
#Code to dedupe date and product which will end up being different lengths. These two lists are populated by the two for loops below
prod_deduped = []
dates_deduped = []
for unique_prodz in prod_numbers:
if unique_prodz not in prod_deduped:
prod_deduped.append(unique_prodz)
for unique_date in datesz:
if unique_date not in dates_deduped:
dates_deduped.append(unique_date)
#Now for the fun part. Time to sum by date and product. The three lists below are empty until we run the code
converted_net_amount = []
prod_id_final = []
date_final = []
#I zipped the list together using itertools which I imported at the top
for unique_product, unique_date in zip_longest(prod_deduped, dates_deduped, fillvalue = ''):
indices = []
zipped_object = zip(prod_numbers, datesz)
zipped_list = list(zipped_object)
for i,[x, y] in enumerate(zipped_list):
if x == unique_product and y == unique_date:
indices.append(i)
converted_total = 0
for index in indices:
converted_total += converted_quant[index]
converted_net_amount.append[converted_total]
first_index = zipped_list.index([unique_product, unique_date])
prod_id_final.append(prod_numbers[first_index])
date_final.append(datesz[first_index])
from collections import defaultdict
summed_dictionary = defaultdict(int)
for x, y, z in list:
summed_dictionary[(x,y)] += z
Using defaultdict should solve your problem and is a lot easier on the eyes than all your code above. I saw this on reddit this morning and figured you crossposted. Credit to the guy from reddit on /r/learnpython

for each gives different result?

I tried to add the comma seprated value between the : seprated then multiply the whole value
For example, consider my value is 1,2,3:4,5,6
I want to add the 1+2+3 ,and 4+5+6 then multiply the result of this value so answer is 6 * 15 = 90
For my bellow data i want the result is 7.224 but this script gives 61.658886435
I don't know what is the problem in my script'
ar = "0.212,1.231,0.112:1.001,3.212,0.002:0.002,0.0001,1.1"
x_data = ar.split(":")
x_final = 1
x_add = 0
for i in x_data:
x_each = i.split(",")
for j in x_each:
x_add = x_add + float(j)
x_final = x_add * x_final
print x_final
Is any possible way to get the result without iterating loop? For above problem
This problem could be also solved in a functional way:
You have to multiply all values in the list - this is what functools.reduce + operator.mul for
You have to sum up all values in all inner lists - this is what sum for
Example:
In [5]: ar = "0.212,1.231,0.112:1.001,3.212,0.002:0.002,0.0001,1.1"
In [6]: import operator
In [7]: import functools
In [8]: functools.reduce(operator.mul, (sum(float(x) for x in s.split(',')) for s in ar.split(':')))
Out[8]: 7.223521582500001
I don't necessarily recommend this complicated expression, but you can do it with list comprehensions and avoid the for loops:
import operator
ar = "0.212,1.231,0.112:1.001,3.212,0.002:0.002,0.0001,1.1"
reduce(operator.mul, [sum([float(n) for n in e]) for e in [x.split(',') for x in ar.split(":")]], 1)
Use missed the initialize value as zero (x_add = 0) in each iterating. So your script add with the previous values
ar = "0.212,1.231,0.112:1.001,3.212,0.002:0.002,0.0001,1.1"
x_data = ar.split(":")
x_final = 1
for i in x_data:
x_each = i.split(",")
x_add = 0 # Here you not initialize it
for j in x_each:
x_add = x_add + float(j)
x_final = x_add * x_final
print x_final
!!! As from #jpmc26 and #soon comment. Avoid using eval, and conform your input string format.
Without looping use regex for to do it
Use regex for solve your problem without looping.
ar = "0.212,1.231,0.112:1.001,3.212,0.002:0.002,0.0001,1.1"
import re
ar = "("+ar #Add the ( with your data
ar = re.sub(r",","+",ar) #Substitute with + instead of ,
ar = re.sub(r"(?=\:|$)",")",ar) #look ahead for add `)` after colon
ar = re.sub(r"(?<=)\:","*(",ar) #Replace the color with *
#NOw you data look likes(0.212+1.231+0.112)*(1.001+3.212+0.002)*(0.002+0.0001+1.1)
#Finally evaluvate the string as a expression
print eval(ar)

Analog of templates in Python

As part of some simulations I'm running I need to output the cumulative distribution of the output of some algorithms:
tests = []
numtests = 100
for i in range(0, numtests):
#random
zeros = [0] * 1024
ones = [1] * 10
#ones = [randint(0,1023) for _ in range(0,10)]
input = zeros + ones
shuffle(input)
tests.append(HGBSA(input,10))
count = [x[0] for x in tests]
found = [x[1] for x in tests]
found.sort()
num = Counter(found)
freqs = [x for x in num.values()]
cumsum = [sum(item for item in freqs[0:rank+1]) for rank in range(len(freqs))]
normcumsum = [float(x)/numtests for x in cumsum]
print(freqs)
print(cumsum)
print(normcumsum)
print(sorted(num.keys()))
figure(0)
plt.plot(sorted(num.keys()), normcumsum)
plt.xlim(0,100)
plt.show()
As the above code shows, I'm running my algorithm 100 times with randomly generated input and then creating a cumulative distribution from the results.
I want to do a similar thing with other algorithms, and in c++ I could write a template class/template function which took a (pointer to a) method as am argument.
I'd like to ask if there is a way in python to create a function/class which produces the output I want, but takes a function as an input, so I avoid duplicating code all over the place.
This is simple to do in Python. You can pass functions (or classes) around like anything else.
def run_test(test_function):
tests = []
numtests = 100
for i in range(0, numtests):
#random
zeros = [0] * 1024
ones = [1] * 10
#ones = [randint(0,1023) for _ in range(0,10)]
input = zeros + ones
shuffle(input)
tests.append(test_function(input,10))
count = [x[0] for x in tests]
found = [x[1] for x in tests]
found.sort()
num = Counter(found)
freqs = [x for x in num.values()]
cumsum = [sum(item for item in freqs[0:rank+1]) for rank in range(len(freqs))]
normcumsum = [float(x)/numtests for x in cumsum]
print(freqs)
print(cumsum)
print(normcumsum)
print(sorted(num.keys()))
figure(0)
plt.plot(sorted(num.keys()), normcumsum)
plt.xlim(0,100)
plt.show()
run_test(HGBSA)
run_test(SOME_OTHER_FUNCTION)
I am not sure that i understand the question, but sounds like you want to pass a function as function argument? You can do that right of the bat in python as everything is passed by reference and nothing stops you from passing a reference to a function as an argument.

Categories

Resources