简体   繁体   中英

Find minimum in a list of tuple among those tuples whose first elements are within a specific range

I have a list of tuples as follows:

list = [(9.9394, 0.9924), (9.8428, 0.6171), (9.9023, 0.5584), (9.8369, 1.0), (9.2106, 0.5339), (9.9748, 0.7131), (9.3257, 0.02725), (11.2865, 0.849), (10.4556, 0.7542), (10.1655, 0.9792), (10.3677, 0.5712), (10.5253, 0.8986), (10.5186, 0.5215)]

I want to make another list made of 7 elements in which each element is the minimum value among list 's second elements whose first elements are within a specific range.

The first element would correspond to bin (8.0,8.6), the second element would correspond to bin (8.6,9.2), the third element to bin (9.2,9.8), the fourth to bin (9.8,10.4), the fifth to bin (10.4,11.0), the sixth to bin (11.0,11.6), and finally the seventh to bin (11.6,12.2) all corresponding to the first elements of tuples in list .

Example: the fourth element would correspond to the fourth bin (9.8,10.4). There are 7 tuples in list whose first elements lie within this range:

(9.9394, 0.9924), (9.8428, 0.6171), (9.9023, 0.5584), (9.8369, 1.0), (9.2106, 0.5339), (9.9748, 0.7131), (9.3257, 0.02725)

So, my 4th element of the new list should be the minimum among second elements:

0.9924, 0.6171, 0.5584, 1.0, 0.5339, 0.7131, 0.02725

which is 0.02725

Is there any shorter version of the following code to establish all seven elements and hence the new list of minima in this manner? The shortest answer will be accepted.

dm7=0.6
item1, item2, item3, item4, item5, item6, item7 = 0, 0, 0, 0, 0, 0, 0
set1, set2, set3, set4, set5, set6, set7 = [], [], [], [], [], [], []
list = [(9.9394, 0.9924), (9.8428, 0.6171), (9.9023, 0.5584), (9.8369, 1.0), (9.2106, 0.5339), (9.9748, 0.7131), (9.3257, 0.02725), (11.2865, 0.849), (10.4556, 0.7542), (10.1655, 0.9792), (10.3677, 0.5712), (10.5253, 0.8986), (10.5186, 0.5215)]

for item in list:
    if (8. +  0*dm7 <= item[0] <= 8. +  1*dm7):
        set1.append(item[1]) 
        item1 = min(set1)
    elif (8. +  1*dm7 <= item[0] <= 8. +  2*dm7):
        set2.append(item[1])
        item2 = min(set2)
    elif (8. +  2*dm7 <= item[0] <= 8. +  3*dm7):
        set3.append(item[1])
        item3 = min(set3)
    elif (8. +  3*dm7 <= item[0] <= 8. +  4*dm7):
        set4.append(item[1])
        item4 = min(set4)
    elif (8. +  4*dm7 <= item[0] <= 8. +  5*dm7):
        set5.append(item[1])
        item5 = min(set5)
    elif (8. +  5*dm7 <= item[0] <= 8. +  6*dm7):
        set6.append(item[1])
        item6 = min(set6)
    elif (8. +  6*dm7 <= item[0] <= 8. +  7*dm7):
        set7.append(item[1])
        item7 = min(set7)

new_list = [item1, item2, item3, item4, item5, item6, item7]

This is what I came up with, assuming I understand your scenario.

from bisect import bisect

items = [(9.9394, 0.9924), (9.8428, 0.6171), (9.9023, 0.5584), (9.8369, 1.0), (9.2106, 0.5339), (9.9748, 0.7131), (9.3257, 0.02725), (11.2865, 0.849), (10.4556, 0.7542), (10.1655, 0.9792), (10.3677, 0.5712), (10.5253, 0.8986), (10.5186, 0.5215)]

thresholds = [x / 10 for x in range(80, 123, 6)] # [8.0, 8.6, 9.2, 9.8, 10.4, 11.0, 11.6, 12.2]
bins = [list() for _ in range(len(thresholds) - 1)] # Set number of bins to 1 less than threshold points

for sorting_key, value in items: # Iterate over items to place into respective bin
    bins[bisect(thresholds, sorting_key) - 1].append(value)

from pprint import pprint
pprint(bins)

To which the output would be:

[[],
 [],
 [0.5339, 0.02725],
 [0.9924, 0.6171, 0.5584, 1.0, 0.7131, 0.9792, 0.5712],
 [0.7542, 0.8986, 0.5215],
 [0.849],
 []]

If you needed to get the minimum value, just use the built-in min() function on each.

min_each = [min(b) if b else None for b in bins] # [None, None, 0.02725, 0.5584, 0.5215, 0.849, None]

In the above code, I'm not using map(min, bins) since min() cannot operate on empty lists.

You can use numpy for a performance boost. With numpy.digitize you can compute the group to which each item belongs. Then with some reshaping you can compute the minimum for each group.

import numpy as np


items = [(9.9394, 0.9924), (9.8428, 0.6171), (9.9023, 0.5584), (9.8369, 1.0), (9.2106, 0.5339), (9.9748, 0.7131), (9.3257, 0.02725), (11.2865, 0.849), (10.4556, 0.7542), (10.1655, 0.9792), (10.3677, 0.5712), (10.5253, 0.8986), (10.5186, 0.5215)]
items = np.asarray(items)

bins = np.linspace(8.0, 12.2, 8)
indices = np.digitize(items[:, 0], bins)  # Check which item corresponds to which bin.
mask = np.tile(indices, (bins.size, 1)) == np.arange(bins.size)[:, None]  # For each group check the members.

result = np.where(mask, items[:, 1], np.inf).min(axis=1)
result[result == np.inf] = 0  # Set default value if no items are available for that group.

print('result: ', result)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM