def w_distance(wed, threshold, cost=None, alpha=-1.0, binary=True, ids=None): ''' Generate a Weights object based on a threshold distance using a WED Parameters ---------- wed: PySAL Winged Edged Data Structure distance: float network threshold distance for neighbor membership cost: defaults to length, can be any cost dicationary {(edge): cost} Returns ------- ps.W(neighbors): PySAL Weights Dict ''' if cost is None: cost = edge_length(wed) if ids: ids = np.array(ids) else: ids = np.arange(len(wed.node_list)) neighbors = {} if binary is True: for node in wed.node_list: near, pred = threshold_distance(wed, cost, node, threshold) neighbors[ids[node]] = near return ps.W(neighbors, None, ids) elif binary is False: weights = {} for node in wed.node_list: wt = [] near, pred = threshold_distance(wed, cost, node, threshold) near.remove(node) neighbors[ids[node]] = near for end in near: path = [end] previous = pred[end] while previous != node: path.append(previous) end = previous previous = pred[end] path.append(node) cum_cost = 0 for p in range(len(path) - 1): cum_cost += cost[(path[p], path[p + 1])] wt.append(cum_cost ** alpha) weights[ids[node]] = wt return ps.W(neighbors, weights, ids)
def poly2Weights(ssdo, contiguityType="ROOK", rowStandard=True): """Uses GP Polygon Neighbor Tool to construct contiguity relationships and stores them in PySAL Sparse Spatial Weights class. INPUTS: ssdo (class): instance of SSDataObject [1] contiguityType {str, ROOK}: ROOK or QUEEN contiguity rowStandard {bool, True}: whether to row standardize the spatial weights NOTES: (1) Data must already be obtained using ssdo.obtainData() or ssdo.obtainDataGA () """ neighbors = {} weights = {} polyNeighDict = WU.polygonNeighborDict(ssdo.inputFC, ssdo.masterField, contiguityType=contiguityType) for masterID, neighIDs in UTILS.iteritems(polyNeighDict): orderID = ssdo.master2Order[masterID] neighbors[orderID] = [ssdo.master2Order[i] for i in neighIDs] w = PYSAL.W(neighbors) if rowStandard: w.transform = 'R' return w
def w_links(wed): """ Generate Weights object for links in a WED Parameters ---------- wed: PySAL Winged Edged Data Structure Returns ps.W(neighbors): PySAL Weights Dict """ nodes = wed.node_edge.keys() neighbors = {} for node in nodes: lnks = wed.enum_links_node(node) # put i,j s.t. i < j lnks = [tuple(sorted(lnk)) for lnk in lnks] for comb in combinations(range(len(lnks)), 2): l, r = comb if lnks[l] not in neighbors: neighbors[lnks[l]] = [] neighbors[lnks[l]].append(lnks[r]) if lnks[r] not in neighbors: neighbors[lnks[r]] = [] neighbors[lnks[r]].append(lnks[l]) return ps.W(neighbors)
def setUp(self): self.neighbors = {'c': ['b'], 'b': ['c', 'a'], 'a': ['b']} self.weights = {'c': [1.0], 'b': [1.0, 1.0], 'a': [1.0]} self.id_order = ['a', 'b', 'c'] self.weights = {'c': [1.0], 'b': [1.0, 1.0], 'a': [1.0]} self.w = pysal.W(self.neighbors, self.weights, self.id_order) self.y = np.array([0, 1, 2])
def WSP2W(wsp): """ Convert a pysal WSP object (thin weights matrix) to a pysal W object. Parameters ---------- wsp : WSP PySAL sparse weights object Returns ------- w : W PySAL weights object Examples -------- >>> import pysal Build a 10x10 scipy.sparse matrix for a rectangular 2x5 region of cells (rook contiguity), then construct a PySAL sparse weights object (wsp). >>> sp = pysal.weights.lat2SW(2, 5) >>> wsp = pysal.weights.WSP(sp) >>> wsp.n 10 >>> print wsp.sparse[0].todense() [[0 1 0 0 0 1 0 0 0 0]] Convert this sparse weights object to a standard PySAL weights object. >>> w = pysal.weights.WSP2W(wsp) >>> w.n 10 >>> print w.full()[0][0] [ 0. 1. 0. 0. 0. 1. 0. 0. 0. 0.] """ wsp.sparse indices = wsp.sparse.indices data = wsp.sparse.data indptr = wsp.sparse.indptr id_order = wsp.id_order if id_order: # replace indices with user IDs indices = [id_order[i] for i in indices] else: id_order = range(wsp.n) neighbors, weights = {}, {} start = indptr[0] for i in xrange(wsp.n): oid = id_order[i] end = indptr[i + 1] neighbors[oid] = indices[start:end] weights[oid] = data[start:end] start = end ids = copy.copy(wsp.id_order) w = pysal.W(neighbors, weights, ids) w._sparse = copy.deepcopy(wsp.sparse) w._cache['sparse'] = w._sparse return w
def w_knn(wed, n, cost=None, ids=None): ''' Generate w Weights object based on the k-nearest network neighbors. Parameters ---------- wed: PySAL Winged Edged Data Structure n: integer number of neighbors for each node cost: defaults to length, can be any cost dictionary Returns ------- ps.W(neighbors): PySAL Weights Dict ''' if cost is None: cost = edge_length(wed) if ids: ids = np.array(ids) else: ids = np.arange(len(wed.node_list)) neighbors = {} for node in wed.node_list: neighbors[node] = knn_distance(wed, cost, node, n=n) return ps.W(neighbors, id_order=ids)
def w_union(w1, w2, silent_island_warning=False): """ Returns a binary weights object, w, that includes all neighbor pairs that exist in either w1 or w2. Parameters ---------- w1 : W object w2 : W object silent_island_warning : boolean Switch to turn off (default on) print statements for every observation with islands Returns ------- w : W object Notes ----- ID comparisons are performed using ==, therefore the integer ID 2 is equivalent to the float ID 2.0. Returns a matrix with all the unique IDs from w1 and w2. Examples -------- Construct rook weights matrices for two regions, one is 4x4 (16 areas) and the other is 6x4 (24 areas). A union of these two weights matrices results in the new weights matrix matching the larger one. >>> import pysal >>> w1 = pysal.lat2W(4,4) >>> w2 = pysal.lat2W(6,4) >>> w = pysal.weights.w_union(w1, w2) >>> w1[0] == w[0] True >>> w1.neighbors[15] [11, 14] >>> w2.neighbors[15] [11, 14, 19] >>> w.neighbors[15] [19, 11, 14] >>> """ neighbors = dict(w1.neighbors.items()) for i in w2.neighbors: if i in neighbors: add_neigh = set(neighbors[i]).union(set(w2.neighbors[i])) neighbors[i] = list(add_neigh) else: neighbors[i] = copy.copy(w2.neighbors[i]) return pysal.W(neighbors, silent_island_warning=silent_island_warning)
def w_subset(w1, ids, silent_island_warning=False): """ Returns a binary weights object, w, that includes only those observations in ids. Parameters ---------- w1 : W object ids : list A list containing the IDs to be include in the returned weights object. silent_island_warning : boolean Switch to turn off (default on) print statements for every observation with islands Returns ------- w : W object Examples -------- Construct a rook weights matrix for a 6x4 region (24 areas). By default PySAL assigns integer IDs to the areas in a region. By passing in a list of integers from 0 to 15, the first 16 areas are extracted from the previous weights matrix, and only those joins relevant to the new region are retained. >>> import pysal >>> w1 = pysal.lat2W(6,4) >>> ids = range(16) >>> w = pysal.weights.w_subset(w1, ids) >>> w1[0] == w[0] True >>> w1.neighbors[15] [11, 14, 19] >>> w.neighbors[15] [11, 14] >>> """ neighbors = {} ids_set = set(list(ids)) for i in ids: if i in w1.neighbors: neigh_add = ids_set.intersection(set(w1.neighbors[i])) neighbors[i] = list(neigh_add) else: neighbors[i] = [] return pysal.W(neighbors, id_order=list(ids), silent_island_warning=silent_island_warning)
def test_islands(self): w = pysal.W(neighbors={ 'a': ['b'], 'b': ['a', 'c'], 'c': ['b'], 'd': [] }) self.assertEqual(w.islands, ['d']) self.assertEqual(self.w3x3.islands, [])
def test_max_neighbors(self): w = pysal.W(neighbors={ 'a': ['b'], 'b': ['a', 'c'], 'c': ['b'], 'd': [] }) self.assertEqual(w.max_neighbors, 2) self.assertEqual(self.w3x3.max_neighbors, 4)
def generateWeightsUsingShapefile(shapeFilePath, idVariable=None, weights=None, kind="queen", k=None, binary=False): # use weights from shapefile for purely geographic w = None if weights == None: if kind == "queen": w = pysal.queen_from_shapefile(shapeFilePath, idVariable=idVariable) if kind == "rook": w = pysal.rook_from_shapefile(shapeFilePath, idVariable=idVariable) if kind == "knn" and type(k) == int: w = pysal.knnW_from_shapefile(shapefile=shapeFilePath, k=k, idVariable=idVariable) if kind == "band": threshold = pysal.min_threshold_dist_from_shapefile( shapeFilePath, idVariable=idVariable) if binary == True: w = pysal.weights.DistanceBand.from_shapefile( shapeFilePath, threshold=threshold, binary=True, idVariable=idVariable) else: w = pysal.threshold_continuousW_from_shapefile( shapefile=shapeFilePath, threshold=threshold, idVariable=idVariable) if kind == "kernel": w = pysal.adaptive_kernelW_from_shapefile(shapeFilePath, diagonal=True, k=5, idVariable=idVariable) # else use user defined weights to create "space" instead of "place" else: if kind == "rook": w = pysal.rook_from_shapefile(shapeFilePath, idVariable=idVariable) if kind == "knn": w = pysal.knnW_from_shapefile(shapeFilePath, k=k, idVariable=idVariable) else: w = pysal.queen_from_shapefile(shapeFilePath, idVariable=idVariable) neighbors = w.neighbor_offsets w = pysal.W(neighbors, weights=weights) # row standardize the matrix. better to do it here and use it somewhere else. w.transform = 'r' if binary == True: w.transform = 'b' return w
def test_full(self): neighbors = {'first': ['second'], 'second': ['first', 'third'], 'third': ['second']} weights = {'first': [1], 'second': [1, 1], 'third': [1]} w = pysal.W(neighbors, weights) wf, ids = pysal.full(w) wfo = np.array([[0., 1., 0.], [1., 0., 1.], [0., 1., 0.]]) np.testing.assert_array_almost_equal(wfo, wf, decimal=8) idso = ['first', 'second', 'third'] self.assertEquals(idso, ids)
def generateWeightsFromScratch(neighbors, weights=None): w = None if weights == None: w = pysal.w(neighbors) else: w = pysal.W(neighbors, weights=weights) # row standardize the matrix. better to do it here and use it somewhere else. w.transform = 'r' return w
def higher_order_sp(wsp, k=2): """ Contiguity weights for a sparse W for order k Arguments ========= wsp: WSP instance k: Order of contiguity Return ------ wk: WSP instance binary sparse contiguity of order k Notes ----- Lower order contiguities are removed. Examples ------- >>> import pysal >>> w25 = pysal.lat2W(5,5) >>> w25.n 25 >>> ws25 = w25.sparse >>> ws25o3 = pysal.weights.higher_order_sp(ws25,3) >>> w25o3 = pysal.weights.higher_order(w25,3) >>> w25o3[12] {1: 1.0, 3: 1.0, 5: 1.0, 9: 1.0, 15: 1.0, 19: 1.0, 21: 1.0, 23: 1.0} >>> pysal.weights.WSP2W(ws25o3)[12] {1: 1.0, 3: 1.0, 5: 1.0, 9: 1.0, 15: 1.0, 19: 1.0, 21: 1.0, 23: 1.0} >>> """ wk = wsp**k rk,ck = wk.nonzero() sk = set(zip(rk,ck)) for j in range(1,k): wj = wsp**j rj,cj = wj.nonzero() sj = set(zip(rj,cj)) sk.difference_update(sj) d= {} for pair in sk: k,v = pair if d.has_key(k): d[k].append(v) else: d[k] = [v] return pysal.weights.WSP(pysal.W(neighbors=d).sparse)
def gpd_contiguity(gpdf): """ Contiguity weights https://github.com/pysal/pysal/blob/master/pysal/weights/_contW_binning.py """ polygons = gpd_polygons(gpdf) neighbors = pysal.weights.\ Contiguity.ContiguityWeightsPolygons(polygons).w # neighbors = pysal.weights.\ # Contiguity.ContiguityWeightsPolygons(polygons, 2).w # for rook return pysal.W(neighbors)
def setUp(self): self.neighbors = {'c': ['b'], 'b': ['c', 'a'], 'a': ['b']} self.weights = {'c': [1.0], 'b': [1.0, 1.0], 'a': [1.0]} self.id_order = ['a', 'b', 'c'] self.weights = {'c': [1.0], 'b': [1.0, 1.0], 'a': [1.0]} self.w = pysal.W(self.neighbors, self.weights, self.id_order) self.y = np.array([0, 1, 2]) self.wlat = pysal.lat2W(3, 3) self.ycat = ['a', 'b', 'a', 'b', 'c', 'b', 'c', 'b', 'c'] self.ycat2 = ['a', 'c', 'c', 'd', 'b', 'a', 'd', 'd', 'c'] self.ym = np.vstack((self.ycat, self.ycat2)).T self.random_seed = 503
def layerToW(layer, wType='ROOK'): polys = [] ids = [] v2p = defaultdict(set) iterator = layer.getFeatures() if wType == 'QUEEN': i = 0 for feat in iterator: geom = feat.geometry() if geom.wkbType() == 6: #multipolygon polys = geom.asMultiPolygon() else: polys = [geom.asPolygon()] # polygon for poly in polys: for ring in poly: for v in ring: v2p[v].add(i) i += 1 else: #Rook e2p = defaultdict(set) i = 0 for feat in iterator: geom = feat.geometry() if geom.wkbType() == 6: #multipolygon polys = geom.asMultiPolygon() else: polys = [geom.asPolygon()] #polygon for poly in polys: for ring in poly: nv = len(ring) for o, d in zip(ring[:-1], ring[1:]): key = tuple(sorted([o, d], key=lambda e: (e[0], e[1]))) e2p[key].add(i) #e2p[d,o].add(i) i += 1 v2p = e2p n = i neighbors = defaultdict(set) for v in v2p: vn = v2p[v] if len(vn) > 1: for i, j in combinations(vn, 2): neighbors[i].add(j) neighbors[j].add(i) return pysal.W(neighbors)
def get_weight(query_res, w_type='knn', num_ngbrs=5): """ Construct PySAL weight from return value of query @param query_res dict-like: query results with attributes and neighbors """ neighbors = {x['id']: x['neighbors'] for x in query_res} print 'len of neighbors: %d' % len(neighbors) built_weight = ps.W(neighbors) built_weight.transform = 'r' return built_weight
def spw_from_shapefile(shapefile, idVariable=None): polygons = pysal.open(shapefile, 'r').read() polygons = map(shapely.geometry.asShape, polygons) perimeters = [p.length for p in polygons] Wsrc = pysal.rook_from_shapefile(shapefile) new_weights = {} for i in Wsrc.neighbors: a = polygons[i] p = perimeters[i] new_weights[i] = [ a.intersection(polygons[j]).length / p for j in Wsrc.neighbors[i] ] return pysal.W(Wsrc.neighbors, new_weights)
def build_W(self, shapefile, type, idVariable=None): """ Building 2 W's the hard way. We need to do this so we can test both rtree and binning """ dbname = os.path.splitext(shapefile)[0] + '.dbf' db = pysal.open(dbname) shpObj = pysal.open(shapefile) neighbor_data = ContiguityWeightsLists(shpObj, type).w neighbors = {} weights = {} if idVariable: ids = db.by_col[idVariable] self.assertEqual(len(ids), len(set(ids))) for key in neighbor_data: id = ids[key] if id not in neighbors: neighbors[id] = set() neighbors[id].update([ids[x] for x in neighbor_data[key]]) for key in neighbors: neighbors[key] = list(neighbors[key]) binningW = pysal.W(neighbors, id_order=ids) else: neighbors[key] = list(neighbors[key]) binningW = pysal.W(neighbors) return binningW
def dwg2w(g, weight_name='weight'): """ Returns a PySAL W object from a directed-weighted graph Parameters ---------- g: networkx digraph weight_name: name of weight attribute of g Returns ------- w: PySAL W Example ------- >>> w = ps.lat2W() >>> w.transform = 'r' >>> g = w2dwg(w) >>> w1 = dwg2w(g) >>> w1.n 25 >>> w1.neighbors[0] [1, 5] >>> w1.neighbors[1] [0, 2, 6] >>> w1.weights[0] [0.5, 0.5] >>> w1.weights[1] [0.33333333333333331, 0.33333333333333331, 0.33333333333333331] """ neighbors = {} weights = {} for node in g.nodes_iter(): neighbors[node] = [] weights[node] = [] for neighbor in g.neighbors_iter(node): neighbors[node].append(neighbor) weight = g.get_edge_data(node, neighbor) if weight: weights[node].append(weight[weight_name]) else: weights[node].append(1) return ps.W(neighbors=neighbors, weights=weights)
def queen_geojson(gjobj): """ Constructs a PySAL queen contiguity W from a geojson object. This is a modification to Serge's code that performs a search for """ features = list(find_features(gjobj))[0] polys = [] ids = [] i = 0 for feature in features: polys.append(ps.cg.asShape(feature['geometry'])) ids.append(i) i += 1 polygons = PolygonCollection(dict(zip(ids, polys))) neighbors = ps.weights.Contiguity.ContiguityWeightsPolygons(polygons).w return ps.W(neighbors)
def get_weight(query_res, w_type='queen', num_ngbrs=5): """ Construct PySAL weight from return value of query :param query_res: query results with attributes and neighbors """ if w_type == 'knn': row_normed_weights = [1.0 / float(num_ngbrs)] * num_ngbrs weights = {x['id']: row_normed_weights for x in query_res} elif w_type == 'queen': weights = { x['id']: [1.0 / len(x['neighbors'])] * len(x['neighbors']) if len(x['neighbors']) > 0 else [] for x in query_res } neighbors = {x['id']: x['neighbors'] for x in query_res} return ps.W(neighbors, weights)
def rm_nan_weight(self, w, array): """Remove nan values from weight matrix Keyword arguments: w Spatial weight matrix. array Numpy array for inventory values. Returns: Weight matrix,array reduced by nan value entries and number of NaN values. """ # Check array shape. print(array.shape) if array.shape != (w.n, 1): # Reshape input array to N,1 dimension. array = array.reshape((w.n, 1)) # Get list of weight ids. idlist = range(len(w.id_order)) # Id list of weight object. !! Ids could be string objects !! wid = w.id_order # Get indices for nan values in array. nanarrayids = [i for i in idlist if np.isnan(array[i])] nanids = [wid[i] for i in nanarrayids] nonanwids = [i for i in wid if i not in nanids] # Filter NaN value indecies from weight matrix dictionaries. newneighbors = { i: filter(lambda x: x not in nanids, w.neighbors[i]) for i in nonanwids } newweights = { i: w.weights[i][:len(newneighbors[i])] for i in nonanwids } # Create new weight matrix with reduced nan free items. neww = pysal.W(newneighbors, newweights, nonanwids) # remove nan values from corresponding input array. newarray = np.array([array[i] for i in idlist if i not in nanarrayids], dtype='d') logger.info("Found %d NAN values in input array -> " "All will be removed prior to Moran's I statistic" % (len(nanids))) return (neww, newarray, len(nanids))
def spw_from_shapefile(shapefile, norm=False): polygons = ps.open(shapefile, 'r').read() spolygons = list(map(asShape, polygons)) spolygons = [fix_mp(p) for p in spolygons] perimeters = [p.length if norm else 1. for p in spolygons] Wsrc = ps.queen_from_shapefile(shapefile) new_weights, edges = {}, {} for i in Wsrc.neighbors: a = spolygons[i] p = perimeters[i] new_weights[i] = [] for j in Wsrc.neighbors[i]: intersect = a.intersection(spolygons[j]) new_weights[i].append(intersect.length) edges[i] = a.length - sum(new_weights[i]) # /a.length return edges, ps.W(Wsrc.neighbors, new_weights)
def get_weight(query_res, w_type='knn', num_ngbrs=5): """ Construct PySAL weight from return value of query @param query_res dict-like: query results with attributes and neighbors """ # if w_type.lower() == 'knn': # row_normed_weights = [1.0 / float(num_ngbrs)] * num_ngbrs # weights = {x['id']: row_normed_weights for x in query_res} # else: # weights = {x['id']: [1.0 / len(x['neighbors'])] * len(x['neighbors']) # if len(x['neighbors']) > 0 # else [] for x in query_res} neighbors = {x['id']: x['neighbors'] for x in query_res} print 'len of neighbors: %d' % len(neighbors) built_weight = ps.W(neighbors) built_weight.transform = 'r' return built_weight
def filter_by_distance_rank(infile, dist, rankfield): '''Thins out a point geodataset so that the selected points represent the maximum rankfield value of all points within the specified distance. Output is a geopandas dataframe. infile: (string) path, filename, and extension of input geodata file (e.g., shapefile) dist: (number, float or integer) minimum distance, in projection units rankfield: (string) fieldname of a numeric ranking field ''' indf = pysal.pdio.read_files(infile) wdist = pysal.weights.DistanceBand.from_dataframe(indf, dist, silent=True) wdw = wdist.weights wdn = wdist.neighbors for fid in wdist: nwpairs = [(k, indf[rankfield][k]) for k in fid[1].iterkeys()] newdic = dict(nwpairs) wdw.update({fid[0]: newdic.values()}) wdn.update({fid[0]: newdic.keys()}) wnew = pysal.W(wdn, wdw, silent_island_warning=True) keeplst = [] procd = [] for nwfid in wnew: idx = nwfid[0] if len(nwfid[1].keys()) > 0: fdict = nwfid[1] iwght = indf[rankfield][idx] fdict.update({idx: iwght}) winner = fdict.keys()[fdict.values().index(max(fdict.values()))] if winner not in procd: keeplst.append(winner) procd = procd + wdn[winner] procd.append(winner) else: keeplst.append(idx) procd.append(idx) keeplst = list(set(keeplst)) return indf.iloc[keeplst]
def adjl2w(adjacency_list, nodetype=str): """ Create a PySAL W object from an adjacency list file Parameters ---------- adjacency_list: list of adjacencies for directed graphs list only outgoing adjacencies nodetype: type for node (str, int, float) Returns ------- W: PySAL W Example ------- >>> al = [[1], [0,2], [1,3], [2]] >>> w = adjl2w(al) >>> w.n 4 >>> w.neighbors['0'] ['1'] >>> w = adjl2w(al, nodetype=int) >>> w.n 4 >>> w.neighbors[0] [1] """ adjacency_list = [map(nodetype, neighs) for neighs in adjacency_list] return ps.W( dict([(nodetype(i), neighs) for i, neighs in enumerate(adjacency_list)]))
def test_threshold_binaryW_from_array(self): points = [(10, 10), (20, 10), (40, 10), (15, 20), (30, 20), (30, 30)] w = pysal.threshold_binaryW_from_array(points, threshold=11.2) self.assertEquals(w.weights, { 0: [1, 1], 1: [1, 1], 2: [], 3: [1, 1], 4: [1], 5: [1] }) self.assertTrue( neighbor_equality( w, pysal.W({ 0: [1, 3], 1: [0, 3], 2: [], 3: [0, 1], 4: [5], 5: [4] })))
def Show(self): self.dialog.Fit() if self.dialog.ShowModal() == wx.ID_OK: import pysal time_gstar = dict() time_gstar_z = dict() if self.rdo_createweight.GetValue(): if len(self.txt_p_neighbors.GetValue()): self.n_p_neighbors = int(self.txt_p_neighbors.GetValue()) if len(self.txt_f_neighbors.GetValue()): self.n_f_neighbors = int(self.txt_f_neighbors.GetValue()) if self.n_p_neighbors ==0 and self.n_f_neighbors==0: return False n_previous = self.n_p_neighbors n_future = self.n_f_neighbors tneighbors = self.create_time_w(n_previous, n_future) tweights = pysal.W(tneighbors) dlg = wx.FileDialog( self.main, message="Save the time weights file as ...", defaultFile=self.shape_name +'.time.gal', wildcard="Weights file (*.gal)|*.gal|All files (*.*)|*.*", style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: save_weight_path = dlg.GetPath() o = pysal.open(save_weight_path,'w') o.write(tweights) o.close() dlg.Destroy() self.weight_path = save_weight_path self.dialog.Destroy() return self.weight_path self.dialog.Destroy() return False