list_1 =[1, 2, 3, 4 ]
def fun(list_1):
for each value in list1:
# perform some operation and create a new data frame(pandas) for each value in the list
# so in total I should get 4 data frames.
print each_value
return new_data_frame
When I run fun(list_1) I should get 4 data frames:
1
data_frame_1
2
data_frame_2
3
data_frame_3
4
data_frame_4
but I am getting an ouput only with first value.
1
data_frame_1
so what should I change in my function.
When you return from the function, it's over.
You're out of the function and that's it.
You could use a generator to achieve what you want or you may return a tuple or a list.
Using a generator :
def fun(list_1):
for each_value in list_1:
# perform some operation and create a new data frame(pandas) named "new_data_frame" for each value in the list
print each_value
yield new_data_frame
for data_frame in fun(list_1):
# Do something with the data frame "data_frame"
This will print the value each time, and return your data frame.
But it returns a generator, so you have to call the function multiple times. What you cannot really do is get your data frames in a loop without wanting to store them in an list or assimilated or call the function only once.
A simpler way with a list could be:
def fun(list_1):
data_frames = []
for each_value in list1:
# perform some operation and create a new data frame(pandas) named "new_data_frame" for each value in the list
print each_value
data_frames.append(new_data_frame)
return data_frames
For reference, I'd suggest you have a look at What does the "yield" keyword do in Python?
which may be interesting for you.
Related
First I tried directly storing values from a list having the name 'data' in an array variable 'c' using loop but 'none' got printed
for i in data:
print(i['name'])
c=i['name']
Here print(i['name']) perfectly worked and output appeared
This is the working ouput
Then I printed c in order to print the values generated using loop. The ouput came as none.
print(c)
Then I tried another way by storing the values and making the array iterable at the same time using for loop. An error occurred which I was unable to resolve.
for i in data:
b[c]=i['name']
c=c+1
The error apeared is as follow-
I have tried two ways, if there is any other way please help me out as I am new to python.
It looks like the variable 'data' is a dictionary.
If you want to add each name from that dictionary to a list:
# create a new list variable
names = []
for i in data:
name = i['name']
print(name)
# add the name to the list
names.append(name)
# output the new list
print(names)
Assuming your data object here is a list like [{"name": "Mr. Green", ...}, {"name": "Mr. Blue", ...}].
If your goal is to end up with c == ["Mr. Green", "Mr. Blue"], then you're looking for something like:
c = []
for i in data:
c.append(i['name'])
print(c)
or you can accomplish tasks like these using list comprehensions like:
c = [i['name'] for i in data]
print(c)
The first code example you posted is iterating through the items in data and reassigning the value of c to each item's name key - not adding them to a list("array"). Without knowing more about the code you ran to produce the screenshot and/or the contents of data, it's hard to say why you're seeing print(c) produce None. I'd guess the last item in data is something like {"name": None, ...} which if it's coming from JSON is possible if the value is null. Small note: I'd generally use .get("name") here instead so that your program doesn't blow up if an item is missing a "name" key entirely.
For your second code example, the error is different but I think falls along a similar logical fallacy which is that lists in python function differently from primitives(things like numbers and strings). For the interpreter to know that b or c are supposed to be lists("arrays"), they need to be instantiated differently and they have their own set of syntax/methods for mutation. For example, like arrays in other languages, lists are indexed by position so doing b[c] = <something> will only work if c is an integer. So something similar to your second example that would also produce a list of names like my above would be:
b = [None] * len(data)
c = 0
for i in data:
b[c]=i['name']
c=c+1
Note that if you only initialize b = [], you get an IndexError: list assignment index out of range on the initial assignment of b[0] = "some name" because the list is of size 0.
Add
b = []
above your first line of code. As the error is saying that you have not (and correctly so) defined the list to append.
I personally would use list comprehension here
b = [obj['name'] for obj in data]
where obj is i as you have defined it.
Sometimes, I have need to write a function that returns a few variables/lists. It might look like this
def returnLists():
list1 = []
list2 = []
var1 = None
# do stuff and add values to list or update var1
return list1, list2, var1
Is there a smoother way to do that? What if instead of 2 lists and 1 variable I have 12 variables I'd like to return, or 8 lists, etc.
The best I have so far is
var = val if 'var' not in locals() else var=var+val
if 'list1' in locals() list1.append(val1) else list=[val1]
Is there a better way to do this in python that doesn't take so many lines? To be clear, it's ok to me that it returns more than 1 variable, I just want to be able to do it where it doesn't take at least 2*variables lines (1 for initialization and 1 for adding/appending the variable)
In my particular case the actual example was I had a pandas dataframe where one column was a baseball stat line AB-H-2B-3B-HR-K-BB (e.g. '33-7-2-0-1-2-4'). I wanted to sum up all the stats. I broke the string into a list and then wanted to sum the list.
So, I opened with
AB=0
H=0
DB=0 #etc
...
BB=0
for game in list:
boxList=game.box.split('-')
ab+=boxList[0]
h+=boxList[1] #etc
...
bb+=boxList[6]
return ab,h,2b,3b,hr,k,bb
I have a function modify as follows:
list_with_chunks = [['hi','hello','how are you?'],['i','am','fine'],['what','about you?','.']]
flatten_list = ['hi','hello',...]
empty_list = []
# building the function to convert our sentences in list_with_chunks into another form:
def modify(sentence):
# do stuff here
# returning the result and appending them in empty_list
return empty_list.append(sentence*2)
I call the function as below:
for i in flatten_list:
modify(i)
But, I want to send each sentence directly from list_with_chunks instead of flattening it and append the result in empty_list. How do I do that?
TIA.
I don't understand the question entirely! But is this what you looking for:
for x in list_with_chunks:
for y in x:
modify(y)
You just need to iterate every element inside list again in order to add them in the empty list.
Use a nested loop through list_with_chunks.
for i in range(len(list_with_chunks)):
for j in range(len(list_with_chunks[i])):
modify(list_with_chunks[i][j], top_n=5)
The list:
li=['check3_dwg_Polyline', 'check2_dwg_Polyline',
'check3_dwg_Polyline_feat_to_polyg',# this will not be needed to extracted
'check2_dwg_Polyline_feat_to_polyg',# >> >>
'check3_dwg_Polyline_feat_to_polyg_feat_to_line',
'check2_dwg_Polyline_feat_to_polyg_feat_to_line']
Purpose
Put the parameters as this:
erase('check3_dwg_Polyline','check3_dwg_Polyline_feat_to_polyg_feat_to_line','output_name')
Useful info: tried sorting the list but didn't fix it.
The purpose is to extract the files from the list and put them in the function erase through a loop.
Like this:
erase('check3_dwg_Polyline','check3_dwg_Polyline_feat_to_polyg_feat_to_line','output_name')
I tried:
a=[li[i:i+3] for i in range(0, len(li), 3)]
for base, base_f, base_line in a:
print(base, base_line, base + "_output") # when it is fixed the
# print will be replaced with
# 'erase' to form the function
and it gives:
check2_dwg_Polyline_feat_to_polyg check2_dwg_Polyline_feat_to_polyg_feat_to_line check2_dwg_Polyline_feat_to_polyg_output
check3_dwg_Polyline check3_dwg_Polyline_feat_to_polyg check3_dwg_Polyline_output
while it should:
check3_dwg_Polyline check3_dwg_Polyline_feat_to_polyg_feat_to_line check3_dwg_Polyline_output
check2_dwg_Polyline check2_dwg_Polyline_feat_to_polyg_feat_to_line check2_dwg_Polyline_output
so later it can be put to function like this:
erase('check3_dwg_Polyline','check3_dwg_Polyline_feat_to_polyg_feat_to_line','output_name')
If you want to call the function erase with the first 3 items of li, you would slice off the first 3 items of the list and call the function with apply:
def erase(a,b,c):
#do something with a,b,c
return
li=['check3_dwg_Polyline', 'check2_dwg_Polyline',
'check3_dwg_Polyline_feat_to_polyg',
'check2_dwg_Polyline_feat_to_polyg',
'check3_dwg_Polyline_feat_to_polyg_feat_to_line',
'check2_dwg_Polyline_feat_to_polyg_feat_to_line']
apply(erase,li[:3])
I have a pandas series which looks like this:
dish_name
Chiken Biryani 3
Mutton Biryani 1
Paneer Biryani 4
Paneer Pulav 2
sandwitch 2
I am calculating (3/(3+1+4+2+2) then second element (1/(3+1+4+2+2) and so on till the end of series.. Which I am doing it with following code in python:
def dish_push(dish_data):
dish_number = len(dish_data)
for i in range(dish_number):
dish = ((dish_data[i])/(dish_data[0:dish_number].sum()))*100
return dish
But when I pass a series to this function it outputs only the last value.
dish_push(dish_quantity_sold)
Out[291]: 16.666666666666664
Where as I am expecting like this..
25.0
8.33333333333
33.3333333333
16.6666666667
16.6666666667
Am I doing some mistake in return statement? Why is it printing the last value? please help.
If dish is your series with the values [3, 1, 4, 2, 2], you can get the result you're looking for without iteration by doing the following:
result = dish / dish.sum() * 100
jonchar already showed the best way to do your specific task, but regarding your question, the problem is that each time through the loop, you are overwriting the dish variable with the series from that iteration. At the end, you return the last dish value from the loop.
What you would need to do is something like this:
def dish_push(dish_data):
dish_number = len(dish_data)
new_data = np.zeros_like(dish_data)
for i in range(dish_number):
new_data[i] = ((dish_data[i])/(dish_data.sum()))*100
return new_data
This would create an array of zeros, put each value in that array, and return the new array after the values have been added.
However, it can be simplified further by using enumerate and looping over the data directly. In each cycle of the loop, this will give you each data point and the index of that data point. Also, you can compute the sum once rather than every time. This also allows you to change the original data in-place, since the sum is already calculated and thus won't change when you change a value. And since the values are changed in-place, you don't have to return anything, since you can just use the array you passed to dish_push (although I will leave the return in just in case):
def dish_push(dish_data):
dish_sum = dish_data.sum()/100
for i, idata in enumerate(dish_data):
dish_data[i] = idata /dish_sum
return dish_data
I realize that this is a rather ugly solution but what you expect it to do is the following:
def dish_push(dish_data):
dish_number = len(dish_data)
dish = []
for i in range(dish_number):
dish.append(((dish_data[i])/(dish_data[0:dish_number].sum()))*100)
return dish
That is, you don't overwrite the result in every iteration but append it to the list.