1

I have a list of lists, such that:

a = [[1,0.8,0.4,0.1,0.3,0.5,1],
     [1,0.8,0.5,0.0,0.3,0.5,1]],
     ........................]

As can be seen in a[1] there is a negative value in the array. At some point later on in my code, I subtract the lowest value away from a constant (in this case it is 1) within a loop, such that:

b = []
for i in range(len(a)):
    b.append(1-min(a[i]))

However this presents a problem as in a[1] I want 1-0.1 and not 1-0.0. The value of 0.0 was originally a negative value (its a noisy data point) and so I used:

a[a<0]=0.0

I cannot remove the value entirely using a=a[a>0.0] as it is important that I keep all of the data points (these are y values that have corresponding x values). I would ideally like to ignore it rather then remove it.

Is there a way I could achieve something like:

b = []
for i in range(len(a)):
    b.append(1-min(a[i]) where min(a[i]) is greater than 0) # i.e. the lowest value that isn't 0
GeoMonkey
  • 1,615
  • 7
  • 28
  • 56
  • possible duplicate of http://stackoverflow.com/questions/26779618/python-find-second-smallest-number or http://stackoverflow.com/questions/28144569/python-3-2-find-second-smallest-number-in-a-list-using-recursion or http://stackoverflow.com/questions/32829203/finding-the-second-smallest-number-using-loops-in-python which is also a duplicate. – Joseph Farah Mar 11 '16 at 02:21
  • Do you want the second smallest value, or do you want the smallest value greater than 0? For `a[1]` they're the same thing, but for `a[0]` they're different. – Steve Jessop Mar 11 '16 at 02:32
  • The smallest value, which may include 0.0. Actually I have inserted an if statement to catch the min values that are zero. Also, the negative value is usually a large value (as its noise and not data) so using abs() may be a solution – GeoMonkey Mar 11 '16 at 03:13

5 Answers5

1

Here is one solution.

b = []
for i in range(len(a)):
    b.append(1 - min(filter(lambda x: x>0, a[i])))

No need remove from source, just do a temporary filter, or even just:

b = map(lambda x : 1 - min(filter(lambda y: y>0, x)), a)
Sam Liao
  • 43,637
  • 15
  • 53
  • 61
0

You can specify a key to min() that makes a 0 higher:

b.append(1-min(a[i], key=lambda x: x if x else 1))

I use 1 because it looks like most of your numbers are below 1. The important thing, though, is that you use a number that you know will not be the lowest. If you have to, you can use math.inf.

zondo
  • 19,901
  • 8
  • 44
  • 83
0

You can use a loop to find the lowest and second lowest value in one pass.

list = [...] #whatever
lowest = 0
secondLowest = 0

if list[0] < list[1]:
    lowest = list[0]
    secondLowest = list[1]
else:
    lowest = list[1]
    secondLowest = list[0]

for i in range(2, len(list)):
    if list[i] < lowest:
        secondLowest = lowest
        lowest = list[i]
    elif list[i] < secondLowest:
        secondLowest = list[i]

This will keep track of the lowest and second lowest values in the array. It starts by setting lowest to the lower of the first to elements, and secondLowest to the other element. Then it iterates through the list, checking to see if any values are lower than the lowest so far, or the second lowest so far.

Matt C
  • 4,470
  • 5
  • 26
  • 44
0

I found an answer I wanted using:

b = []
for i in range(len(a)):
    b.append(1-sorted(x for x in a[i] if x > 0)[0])
GeoMonkey
  • 1,615
  • 7
  • 28
  • 56
-1
def remove_min(lis1):
    # remove the minium element in the list
    lismin=min(lis1)
    newlis=[x for x in lis1 if x!=lismin]
    return newlis
def find_nminimum(lis,n):
    # find the n minimum element and return it
    for i in range(n):
        lis=remove_min(lis)
    return min(lis)

output: find_nminimum(lis,0) gives minimum of the list. find_nminimum(lis,n) gives the nth minimum in the list. I didn't consider exceptions when n>len(lis).

Wanlie
  • 1
  • 4