Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: setting negative values in list to 0

This seems like it would be simple, but I am having an issue with setting negative numbers in a list to 0. Here is my code:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
            list3.append(list1[i]-list2[i])
    if i < 0:
            i = 0
    else:
            i = i
    return list3

I am using this function when making stacked bar charts with matplotlib. Essentially, some values in list2 are larger than values in list1. For the data I have it doesn't make sense to have negative values. Essentially anything with a negative value would just plot as one solid bar.

EDIT: Just wanted to add that the top of the graph is list3.

EDIT 2: Thank you everyone for the help. I ended up using this due to the simplicity:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
            list3.append(max(list1[i]-list2[i], 0))
    return list3

However I appreciate all the solutions and help, I am going to try some of the other examples just for a learning experience.

like image 762
user3826299 Avatar asked Aug 13 '26 02:08

user3826299


2 Answers

One way to do it is to change the list to a numpy array. Then the subtraction is easy and clear, plus you can use numpy.clip to change negative values to 0. numpy arithmetic is also much, much faster (if that's a concern in this case, which seems unlikely) than iterating over python lists.

import numpy as np

ar1 = np.array(list1)
ar2 = np.array(list2)

ar3 = np.clip(ar1 - ar2, 0, None)

If you don't want to use numpy, then just change this line

list3.append(list1[i] - list2[i])

to this

list3.append(max(list1[i] - list2[i], 0))

Finally, when you're iterating over lists to make a new list, it is far more idiomatically python to use a list comprehension:

list3 = [max(item1 - item2, 0) for item1, item2 in zip(list1, list2)]

Of course, if the lists are moderately large, then you have to concern yourself with the fact that zip actually makes a copy of the lists. So if memory usage is too large with zip, you can use izip from the itertools module. It's just a drop-in replacement (in this case) for zip:

from itertools import izip
list3 = [max(item1 - item2, 0) for item1, item2 in izip(list1, list2)]
like image 133
jsw Avatar answered Aug 14 '26 15:08

jsw


You are setting i to zero, not the content of list3[i].

if list3[i] < 0:
    list3[i] = 0

Your else block is setting i=i, which does nothing. You are also lacking one level of indentation for this check, the correct indentation would look like this:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
        list3.append(list1[i]-list2[i])
        if list3[i] < 0:
            list3[i] = 0
return list3

However, I think it would be clearer to write the function like this:

def subtract_lists(list1, list2):        
    list3 = []
    for a,b in zip(list1, list2):
        diff = a - b 
        list3.append(diff if diff > 0 else 0)
    return list3

There are of course more concise solutions (check DrV's answer).

like image 44
timgeb Avatar answered Aug 14 '26 15:08

timgeb