0

Sorry for the large code dump. My problem is with my last for loop. I am attempting to set up a new dictionary, "candidates," that contains all of the possible combinations of one site with another site, mapped to the distance between them. For instance, say that site 1 has ID 1234, site 2 has ID 1235, and site 3 has ID 1236. What I want the candidates dictionary to be eventually is {'1234_1235' : distance, '1234_1236' : distance}, i.e. all possible combinations from one site to other sites. These combinations are already contained in dictkey; I just need to reorganize them. This is so I can pop off the shortest distance, and eventually get a list of the "nearest neighbor" to each site.

for i in np.arange(num_sites):
    lat1 = lat[i]
    lon1 = lon[i]
    site1=site[i]
    rat1 = lat1*np.pi/180.0
    ron1 = lon1*np.pi/180.0
    for j in np.arange(i+1,num_sites):
        lat2 = lat[j]
        lon2 = lon[j]
        site2= site[j]
        rat2 = lat2*np.pi/180.0
        ron2 = lon2*np.pi/180.0

Calculate the distance using the Haversine Formula

        d = 2.0*np.arcsin(np.sqrt((np.sin((rat1-rat2)/2))**2 +
            np.cos(rat1)*np.cos(rat2)*(np.sin((ron1-ron2)/2))**2))

        # dist_arr[i,j] = 6371.0 * d

        dictkey[site1+"_"+site2] = 6371.0*d

temporary = set()
for key in dictkey: 
    parts = key.split("_")
    site_one = parts[0]
    site_two = parts[1]
    temporary.add(site_one)
for temps in temporary:
    candidates = dict()
    for key in dictkey:
        parts = key.split("_")
        site_one = parts[0]
        site_two = parts[1]
        if site_one == temps:
            candidates[site_one] = dictkey[key]
Ravmcgav
  • 183
  • 1
  • 1
  • 11

1 Answers1

0

The simplest way to achive it is to prepare candidates during calculating distance. Just prepare dict of candidates instead of dict_key:

candidates = {}
for i in np.arange(num_sites):
lat1 = lat[i]
lon1 = lon[i]
site1=site[i]
rat1 = lat1*np.pi/180.0
ron1 = lon1*np.pi/180.0
for j in np.arange(i+1,num_sites):
    lat2 = lat[j]
    lon2 = lon[j]
    site2= site[j]
    rat2 = lat2*np.pi/180.0
    ron2 = lon2*np.pi/180.0

    d = 2.0*np.arcsin(np.sqrt((np.sin((rat1-rat2)/2))**2 +
        np.cos(rat1)*np.cos(rat2)*(np.sin((ron1-ron2)/2))**2))


    distance = 6371.0*d
    if site1 in candidates:
        candidates[site1][site2] = distance
    else:
        candidates[site1] = {site2: distance}

    if site2 in candidates:
        candidates[site2][site1] = distance
    else:
        candidates[site2] = {site1: distance}

Solution above would give you dictionary candidates with dictionaries with distance to all other sites. It's of course double sized - it stores same data for 1234-> 4567 and 4567 -> 1234.

candidates.get('1234', {}).get('4567') == candidates.get('4567', {}).get('1234')
>>True

But as you see, it provides easy way of getting values. If you need to get e.g. site with lowest distance to 1234:

import operator
closest_site = sorted(candidates.get('1234', {}).items(), key=operator.itemgetter(1))

taken from answer1

closest_site will be tuple: (<ID of closest site>, <distance>)

Please write if you need more memory efficient solution. This is not optimal, because generate double sized data.

UPDATE

If you need to get ID of original site together with shortest distance site:

closest_site = (candidates.get('1234'),) + sorted(candidates.get('1234', {}).items(), key=operator.itemgetter(1))

then closest_site: (<ID of original site>, <ID of closest site>, <distance>)

Community
  • 1
  • 1
KePe
  • 531
  • 7
  • 7
  • Great, thanks! Is there a way to then have closest_site output the original site as well, so I know which site is the home and which site is the nearest one? Otherwise if I do something like candidates.get(site1, {}) I get all of the nearest neighbor IDs, but not the original site number. Very cool idea though, a dictionary of dictionaries! – Ravmcgav Jun 14 '16 at 22:22