krm76
krm76

Reputation: 356

How to find multiple minimum values from a list of sublists?

I have GPS coordinates for RRH and BBU:

RRH: [[41.38988253, 2.129556023, '1'], [41.38745915, 2.126436603, '2'], [41.3929439, 2.143336753, '3'], [41.39109767, 2.135616075, '4'], [41.39496903, 2.138040811, '5'], [41.39414659, 2.137729336, '6'], [41.38440257, 2.119681252, '7'], [41.3535301, 2.144453223, '8'], [41.35552416, 2.137000697, '9'], [41.35258318, 2.148086036, '10'], [41.35130853, 2.140463315, '11'], [41.38765528, 2.121350735, '12'], [41.36445154, 2.132837518, '13'], [41.36144746, 2.130147294, '14'], [41.34995663, 2.144620381, '15'], [41.38124426, 2.118779226, '16'], [41.36352164, 2.134464983, '17'], [41.3904652, 2.13343991, '18'], [41.39335171, 2.135858918, '19'], [41.38860314, 2.135873516, '20'], [41.39195119, 2.139388009, '21'], [41.40584116, 2.215194359, '22'], [41.41060962, 2.22285246, '23'], [41.40801101, 2.211823094, '24'], [41.40174968, 2.213648607, '25'], [41.40881323, 2.215466548, '26'], [41.40876677, 2.217668089, '27'], [41.40393753, 2.190354235, '28'], [41.40309294, 2.191549143, '29'], [41.40421413, 2.193764487, '30'], [41.40198954, 2.188620978, '31'], [41.40540358, 2.187300951, '32'], [41.3988891, 2.190027392, '33'], [41.40488006, 2.184768114, '34'], [41.40656225, 2.186155734, '35'], [41.4032534, 2.183736817, '36'], [41.40742083, 2.191097044, '37'], [41.39982978, 2.194269803, '38'], [41.38723668, 2.129851845, '39'], [41.39034394, 2.124049766, '40'], [41.38648798, 2.122911378, '41'], [41.40668683, 2.193266381, '42'], [41.41341636, 2.218966707, '43'], [41.41339722, 2.222205598, '44'], [41.39375604, 2.140802106, '45'], [41.38818833, 2.128579772, '46'], [41.38589634, 2.115121354, '47'], [41.39037831, 2.137155264, '48'], [41.40888641, 2.218998806, '49'], [41.41149706, 2.227529451, '50'], [41.407576, 2.217833448, '51'], [41.40577599, 2.190513005, '52'], [41.40461468, 2.190262216, '53'], [41.36564597, 2.131829909, '54'], [41.36489012, 2.131611604, '55'], [41.3655079, 2.13350979, '56'], [41.3545356, 2.138947744, '57'], [41.35294958, 2.138810688, '58'], [41.35525513, 2.142080929, '59'], [41.38541285, 2.117792843, '60'], [41.40350203, 2.16165616, '61'], [41.39407746, 2.163295498, '62'], [41.40256563, 2.159653646, '63'], [41.40345137, 2.158732677, '64'], [41.40573486, 2.160594926, '65'], [41.40544246, 2.158677166, '66'], [41.4042025, 2.156580309, '67'], [41.40639032, 2.156391287, '68'], [41.40497179, 2.154232881, '69'], [41.40737523, 2.158183354, '70'], [41.40208867, 2.154838201, '71'], [41.40271803, 2.152349074, '72'], [41.40072331, 2.157982016, '73'], [41.40094072, 2.152824619, '74'], [41.40515581, 2.151148606, '75'], [41.39161495, 2.154777093, '76'], [41.39164912, 2.1502518, '77'], [41.3933277, 2.153140256, '78'], [41.38964343, 2.155062515, '79'], [41.39104607, 2.158508685, '80'], [41.38904977, 2.15814747, '81'], [41.38731735, 2.155917023, '82'], [41.38731395, 2.151280403, '83'], [41.38455081, 2.148338702, '84'], [41.38051089, 2.1491282, '85'], [41.38050935, 2.154302387, '86'], [41.3830847, 2.153219841, '87'], [41.37746396, 2.152994102, '88'], [41.37864266, 2.158372984, '89'], [41.38162664, 2.160132284, '90'], [41.38477989, 2.157736848, '91'], [41.39646026, 2.166359429, '92'], [41.39531549, 2.161977489, '93'], [41.39386582, 2.165235745, '94'], [41.39303263, 2.168665537, '95'], [41.39052591, 2.16766681, '96'], [41.39528298, 2.170973353, '97'], [41.39307377, 2.173802557, '98'], [41.39026389, 2.172233558, '99'], [41.39198357, 2.176844408, '100'], [41.38705505, 2.168349986, '101'], [41.38580475, 2.169337344, '102'], [41.38489202, 2.170894091, '103'], [41.38374847, 2.170944317, '104'], [41.38320131, 2.171871154, '105'], [41.38229848, 2.171974446, '106'], [41.38164839, 2.172520899, '107'], [41.38141647, 2.173589097, '108'], [41.38060403, 2.173336928, '109'], [41.37981981, 2.174131261, '110'], [41.37907178, 2.175426808, '111'], [41.37856088, 2.176158937, '112'], [41.37770398, 2.175726781, '113'], [41.37723853, 2.176857279, '114'], [41.37667486, 2.177878565, '115'], [41.38657664, 2.171501454, '116'], [41.38796178, 2.17078609, '117'], [41.38852804, 2.172406557, '118'], [41.38889536, 2.168287986, '119'], [41.39089217, 2.165811636, '120'], [41.39265104, 2.163642299, '121'], [41.39437496, 2.161499581, '122'], [41.39594399, 2.159692488, '123'], [41.38726061, 2.17415253, '124'], [41.3867827, 2.17525906, '125'], [41.38613137, 2.175649167, '126'], [41.3854995, 2.176295834, '127'], [41.3851489, 2.176954444, '128'], [41.38455147, 2.175213232, '129'], [41.38377194, 2.174609471, '130'], [41.38284373, 2.176761578, '131'], [41.38426326, 2.178683726, '132'], [41.38321941, 2.179508837, '133'], [41.38554138, 2.173372772, '134'], [41.38070946, 2.17799329, '135'], [41.37906733, 2.1798861, '136'], [41.38106167, 2.181434062, '137'], [41.38414004, 2.18409775, '138'], [41.38487256, 2.185618739, '139'], [41.3829069, 2.186158478, '140'], [41.39647318, 2.158142169, '141'], [41.39541995, 2.156254351, '142'], [41.39543435, 2.153929413, '143'], [41.39442252, 2.152344159, '144'], [41.39458675, 2.150402206, '145'], [41.39349639, 2.148882225, '146'], [41.39309984, 2.146997441, '147'], [41.39269047, 2.145737024, '148'], [41.39216, 2.144617541, '149'], [41.39212191, 2.143791101, '150'], [41.39151727, 2.141423138, '151'], [41.39087681, 2.138892682, '152'], [41.37951535, 2.123255434, '153'], [41.38234159, 2.122750756, '154'], [41.38076059, 2.121654553, '155'], [41.38158784, 2.12511256, '156'], [41.37973609, 2.142609535, '157'], [41.38070643, 2.140787318, '158'], [41.37912693, 2.140125029, '159'], [41.38558235, 2.196101422, '160'], [41.38373742, 2.194310782, '161'], [41.38872536, 2.191850873, '162'], [41.39104446, 2.189013813, '163'], [41.38964624, 2.183705985, '164'], [41.3756532, 2.176672921, '165'], [41.37445512, 2.174137286, '166'], [41.37511963, 2.172150053, '167'], [41.37469855, 2.170009728, '168'], [41.37522149, 2.167265619, '169'], [41.37477745, 2.164891338, '170'], [41.37525678, 2.163534026, '171'], [41.37469573, 2.1615999, '172'], [41.37530681, 2.159561563, '173'], [41.37476511, 2.157728066, '174'], [41.37530116, 2.155975208, '175'], [41.3752681, 2.152972091, '176'], [41.37559207, 2.15040038, '177'], [41.38912147, 2.200525494, '178'], [41.37606258, 2.149193449, '179'], [41.37382267, 2.148593761, '180'], [41.37365726, 2.150790153, '181'], [41.3722869, 2.148909567, '182'], [41.37338846, 2.154652807, '183'], [41.3763164, 2.189202428, '184'], [41.37797628, 2.188494739, '185'], [41.37944773, 2.187923778, '186'], [41.37859323, 2.191248351, '187'], [41.38123405, 2.187259818, '188'], [41.37918489, 2.155172675, '189'], [41.38143976, 2.156791124, '190'], [41.38303894, 2.160313106, '191'], [41.38562105, 2.162507838, '192'], [41.38627958, 2.164671358, '193'], [41.38811461, 2.164473477, '194'], [41.38904783, 2.162547839, '195'], [41.38867274, 2.159556719, '196'], [41.37814521, 2.170763199, '197'], [41.39856273, 2.181141831, '198'], [41.39706339, 2.177725078, '199'], [41.39543338, 2.174173142, '200'], [41.40595965, 2.196085956, '201'], [41.40590057, 2.198644551, '202'], [41.40822011, 2.201575706, '203'], [41.40690119, 2.202357761, '204'], [41.408396, 2.204834417, '205'], [41.40866122, 2.207238278, '206'], [41.40847209, 2.206574199, '207'], [41.40842553, 2.20897442, '208'], [41.40989058, 2.211958916, '209'], [41.4078404, 2.199451041, '210'], [41.42994945, 2.199672708, '211'], [41.42871317, 2.197970163, '212'], [41.42886609, 2.204068146, '213'], [41.42635501, 2.200254099, '214'], [41.42572176, 2.208256698, '215'], [41.42727818, 2.204374155, '216'], [41.42332817, 2.196548327, '217'], [41.4250889, 2.197223711, '218'], [41.42694172, 2.195373298, '219'], [41.43267828, 2.197860268, '220'], [41.40703161, 2.153612625, '221'], [41.40816405, 2.155696109, '222'], [41.40867073, 2.152077178, '223'], [41.41021455, 2.149881192, '224'], [41.40856448, 2.147062842, '225'], [41.41058356, 2.147931309, '226'], [41.40941309, 2.145606571, '227'], [41.4070378, 2.146164866, '228'], [41.41057942, 2.158529623, '229'], [41.40915937, 2.159776124, '230'], [41.39910639, 2.157642354, '231'], [41.39946885, 2.1601829, '232'], [41.39742936, 2.16204943, '233'], [41.39786889, 2.165887234, '234'], [41.39909312, 2.168827544, '235'], [41.39967085, 2.173128868, '236'], [41.40094963, 2.176077127, '237'], [41.40239839, 2.174188933, '238'], [41.40303716, 2.178815456, '239'], [41.40105048, 2.180930452, '240'], [41.40180775, 2.16680983, '241'], [41.40074303, 2.165274684, '242'], [41.40160211, 2.170797932, '243'], [41.40527925, 2.175215203, '244'], [41.40578643, 2.181131991, '245'], [41.4057811, 2.165305951, '246'], [41.40632458, 2.169821608, '247'], [41.40947235, 2.165138472, '248'], [41.40615597, 2.16290471, '249'], [41.40899559, 2.163609208, '250'], [41.41162898, 2.164328687, '251'], [41.40415872, 2.167584134, '252'], [41.40934147, 2.172128646, '253'], [41.41095553, 2.170031558, '254'], [41.40775853, 2.166686358, '255'], [41.40785995, 2.174679854, '256'], [41.41081219, 2.174542492, '257'], [41.40721475, 2.177817663, '258'], [41.40971316, 2.1789005, '259'], [41.41183357, 2.177744727, '260'], [41.38720667, 2.197712891, '261'], [41.38797421, 2.19511995, '262'], [41.38954698, 2.197268152, '263'], [41.39170675, 2.199937827, '264'], [41.39335424, 2.202052066, '265'], [41.38124352, 2.192809131, '266'], [41.37075116, 2.156721231, '267'], [41.37003354, 2.150872323, '268'], [41.36598669, 2.137806, '269'], [41.3671078, 2.14043114, '270'], [41.36629935, 2.136886419, '271'], [41.40244212, 2.193566064, '272'], [41.40338457, 2.197149137, '273'], [41.40147665, 2.197388361, '274'], [41.40429076, 2.199376949, '275'], [41.39955167, 2.195996457, '276'], [41.40156317, 2.199910671, '277'], [41.39941119, 2.198182841, '278'], [41.39747841, 2.197920138, '279'], [41.39916766, 2.200553512, '280'], [41.39742986, 2.200637056, '281'], [41.39771604, 2.202732102, '282'], [41.39760922, 2.204672685, '283'], [41.39649475, 2.203286769, '284'], [41.39715776, 2.205623271, '285'], [41.42645327, 2.202375412, '286'], [41.42849034, 2.20477867, '287'], [41.42781111, 2.20620115, '288'], [41.42467475, 2.203392208, '289'], [41.42710869, 2.207678204, '290'], [41.42416437, 2.205934769, '291'], [41.42370113, 2.210090139, '292'], [41.40610086, 2.149617997, '293'], [41.40662625, 2.148883385, '294'], [41.4077921, 2.150012055, '295'], [41.40693465, 2.15091706, '296'], [41.40565244, 2.150263277, '297'], [41.4045975, 2.150030929, '298'], [41.4038193, 2.150290792, '299'], [41.40210728, 2.150488432, '300']]

BBU: [[41.38227061, 2.128611835, '1'], [41.39517376, 2.147391488, '2'], [41.40538329, 2.156731836, '3'], [41.40832257, 2.168647219, '4'], [41.40323209, 2.206633545, '5'], [41.39397106, 2.193518883, '6'], [41.38212698, 2.189586642, '7'], [41.41882802, 2.199257871, '8'], [41.35910284, 2.136974551, '9'], [41.38131931, 2.176102407, '10'], [41.38918794, 2.177094309, '11'], [41.39325006, 2.156269437, '12'], [41.38385621, 2.161888675, '13'], [41.37208181, 2.162537181, '14'], [41.376809, 2.144989163, '15'], [41.40015888, 2.178641263, '16'], [41.42046079, 2.182838054, '17'], [41.40103642, 2.161985998, '18']]

The code I've written, calculates all possible distances between RRHs and BBUs and stores it in a multidimension lists with the following structure:

# Structure variables "distances"
distances = [[calculated_distance, BBU_id, RRH_id]]
Example: [[115.6, 3, 68]]

To sum up, I have a list of sublists, of 5400 entries.

What I'd like now is to store, out of the distances varibles, in another list, let's calle it "connected_sites", the minimum distance of each RRH to a BBU. So it will end up with a list of 300 sublists.

I don't know how to pick from all the distances the minimums ones for every RRH.

This is the code:

# Libraries
import math
import csv
import operator
# -------------------------------- FUNCTIONS ---------------------------------
# Calculates the distance between two GPS coordinates
def haversine(coord1, coord2):
    R = 6372800  # Earth radius in meters
    lat1, lon1 = coord1
    lat2, lon2 = coord2

    phi1, phi2 = math.radians(lat1), math.radians(lat2) 
    dphi       = math.radians(lat2 - lat1)
    dlambda    = math.radians(lon2 - lon1)

    a = math.sin(dphi/2)**2 + \
        math.cos(phi1)*math.cos(phi2)*math.sin(dlambda/2)**2

    return 2*R*math.atan2(math.sqrt(a), math.sqrt(1 - a))

# Convert GPS coordinates from str to float
def coord2float(l):
    for i in range(len(l)):
        l[i][0]=float(l[i][0])
        l[i][1]=float(l[i][1])    
    return l


# MAIN

# Importing GPS coordinates    
RRH = []
BBU = []
i = 0
with open('sites.csv', newline='\n') as csvfile:
    sites = csv.reader(csvfile, delimiter=';')
    for row in sites:
        if i < 300:
            RRH.append(row)
            i+=1
        else:
            BBU.append(row)
# # Converting file coordinates into floats
RRH = coord2float(RRH)
BBU = coord2float(BBU)

# Calculating the distances between BBU and RRH
distances = []
for i in range(len(BBU)):
    for j in range(len(RRH)):
        coord1 = (BBU[i][0],BBU[i][1])
        coord2 = (RRH[j][0],RRH[j][1])     
        dist = haversine(coord1, coord2)
        distances.append([float("%.1f" % dist), 
                          int(BBU[i][2]),
                          int(RRH[j][2])])# Convert distance to float

distances = sorted(distances, key=operator.itemgetter(0), reverse=False)

Upvotes: 2

Views: 169

Answers (1)

FredrikHedman
FredrikHedman

Reputation: 1253

So in my mind itertools.groupby will solve this problem. I made a copy of the data you provided, put it into the sites.csv and made a few tweaks to the code and added the lines needed to create connected_sites:

# Libraries
import csv
from itertools import groupby


def haversine(coord1, coord2):
    """Calculates the distance between two GPS coordinates"""
    from math import sin, cos, atan2, sqrt, radians
    R = 6372800  # Earth radius in meters
    lat1, lon1 = coord1
    lat2, lon2 = coord2
    phi1, phi2 = radians(lat1), radians(lat2)
    dphi = radians(lat2 - lat1)
    dlambda = radians(lon2 - lon1)
    a = sin(dphi / 2)**2 + cos(phi1) * cos(phi2) * sin(dlambda / 2)**2
    return 2 * R * atan2(sqrt(a), sqrt(1 - a))


def coord2float(lst):
    """Convert GPS coordinates from str to float"""
    for ll in lst:
        ll[0] = float(ll[0])
        ll[1] = float(ll[1])
    return lst

# MAIN

# Importing GPS coordinates
RRH = []
BBU = []
i = 0
with open('sites.csv', newline='') as csvfile:
    sites = csv.reader(csvfile, delimiter=';')
    for row in sites:
        if not row:
            continue
        if i < 300:
            RRH.append(row)
            i += 1
        else:
            BBU.append(row)
# # Converting file coordinates into floats
RRH = coord2float(RRH)
BBU = coord2float(BBU)

# Calculating the distances between BBU and RRH
distances = []
for i in range(len(BBU)):
    for j in range(len(RRH)):
        coord1 = (BBU[i][0], BBU[i][1])
        coord2 = (RRH[j][0], RRH[j][1])
        dist = haversine(coord1, coord2)
        distances.append([float("%.1f" % dist),
                          int(BBU[i][2]),
                          int(RRH[j][2])])  # Convert distance to float


Adding code to first sort the distances calculated with respect to the RRH id. Then use groupby to iterate over each RRH id to calculate the minimum distance using min on the distances calculated for each RRH id:

distances.sort(key=lambda dd: dd[2])

connected_sites = []
for rrh_id, grouped_bbu in groupby(distances, key=lambda dd: dd[2]):
    dist4k = list(grouped_bbu)
    min_dist = min(dist4k, key=lambda dd: dd[0])
    connected_sites.append([min_dist, rrh_id])


print(f'Number connected sites: {len(connected_sites)}')
print(f'First two minimum distances: {connected_sites[:2]}')
print(f'Distances for first two sites: {distances[:36]}')

Running this code on the input data gives the output below. On insecption it is clear that the calculated minimum distance is correct.

Number connected sites: 300
First two minimum distances: [[[850.3, 1, 1], 1], [[605.0, 1, 2], 2]]
Distances for first two sites: [[850.3, 1, 1], [1600.4, 2, 1], 
[2848.5, 3, 1], [3852.8, 4, 1], [6600.3, 5, 1], [5356.6, 6, 1],
[5083.3, 7, 1], [6646.7, 8, 1], [3479.1, 9, 1], [3999.4, 10, 1], 
[3967.6, 11, 1], [2260.3, 12, 1], [2780.1, 13, 1], [3390.6, 14, 1], [1942.5, 15, 1], [4252.1, 16, 1], [5597.0, 17, 1], [2976.7, 18, 1], [605.0, 1, 2], [1947.7, 2, 2], [3219.3, 3, 2], [4217.6, 4, 2], 
[6917.6, 5, 2], [5644.3, 6, 2], [5303.2, 7, 2], [7005.9, 8, 2], 
[3274.3, 9, 2], [4200.6, 10, 2], [4231.6, 11, 2], [2571.4, 12, 2], [2985.5, 13, 2], [3464.5, 14, 2], [1949.5, 15, 2], [4579.3, 16, 2], [5967.8, 17, 2], [3328.5, 18, 2]]

Upvotes: 1

Related Questions