예제 #1
0
 def test_limit_range(self):
     assert list(mm.limit_range(range(10), rng=(25, 75))) == [2, 3, 4, 5, 6, 7]
     assert list(mm.limit_range(range(10), rng=(10, 90))) == [1, 2, 3, 4, 5, 6, 7, 8]
     assert list(mm.limit_range([0, 1], rng=(25, 75))) == [0, 1]
     assert list(
         mm.limit_range(np.array([0, 1, 2, 3, 4, np.nan]), rng=(25, 75))
     ) == [1, 2, 3]
예제 #2
0
    def __init__(self,
                 gdf,
                 values,
                 spatial_weights,
                 unique_id,
                 rng=None,
                 verbose=True):
        try:
            from inequality.gini import Gini
        except ImportError:
            raise ImportError("The 'inequality' package is required.")

        self.gdf = gdf
        self.sw = spatial_weights
        self.id = gdf[unique_id]
        self.rng = rng

        data = gdf.copy()
        if values is not None:
            if not isinstance(values, str):
                data["mm_v"] = values
                values = "mm_v"
        self.values = data[values]

        if self.values.min() < 0:
            raise ValueError(
                "Values contain negative numbers. Normalise data before"
                "using momepy.Gini.")

        data = data.set_index(unique_id)[values]

        if rng:
            from momepy import limit_range

        results_list = []
        for index in tqdm(data.index, total=data.shape[0],
                          disable=not verbose):
            if index in spatial_weights.neighbors.keys():
                neighbours = spatial_weights.neighbors[index].copy()
                if neighbours:
                    neighbours.append(index)

                    values_list = data.loc[neighbours].values

                    if rng:
                        values_list = limit_range(values_list, rng=rng)
                    results_list.append(Gini(values_list).g)
                else:
                    results_list.append(0)
            else:
                results_list.append(np.nan)

        self.series = pd.Series(results_list, index=gdf.index)
예제 #3
0
    def __init__(self,
                 gdf,
                 values,
                 spatial_weights,
                 unique_id,
                 rng=None,
                 mode="mean"):
        self.gdf = gdf
        self.sw = spatial_weights
        self.id = gdf[unique_id]
        self.rng = rng
        self.mode = mode

        data = gdf.copy()
        if values is not None:
            if not isinstance(values, str):
                data["mm_v"] = values
                values = "mm_v"
        self.values = data[values]

        data = data.set_index(unique_id)

        results_list = []
        for index, row in tqdm(data.iterrows(), total=data.shape[0]):
            neighbours = spatial_weights.neighbors[index].copy()
            if neighbours:
                neighbours.append(index)
            else:
                neighbours = [index]

            values_list = data.loc[neighbours][values]

            if rng:
                from momepy import limit_range

                values_list = limit_range(values_list, rng=rng)
            if mode == "mean":
                results_list.append(np.mean(values_list))
            elif mode == "median":
                results_list.append(np.median(values_list))
            elif mode == "mode":
                results_list.append(sp.stats.mode(values_list)[0][0])
            else:
                raise ValueError("{} is not supported as mode.".format(mode))

        self.series = pd.Series(results_list, index=gdf.index)
예제 #4
0
    def __init__(self,
                 gdf,
                 values,
                 spatial_weights,
                 unique_id,
                 rng=None,
                 verbose=True):
        try:
            from inequality.theil import Theil
        except ImportError:
            raise ImportError("The 'inequality' package is required.")

        self.gdf = gdf
        self.sw = spatial_weights
        self.id = gdf[unique_id]
        self.rng = rng

        data = gdf.copy()
        if values is not None:
            if not isinstance(values, str):
                data["mm_v"] = values
                values = "mm_v"
        self.values = data[values]

        data = data.set_index(unique_id)[values]

        if rng:
            from momepy import limit_range

        results_list = []
        for index in tqdm(data.index, total=data.shape[0],
                          disable=not verbose):
            if index in spatial_weights.neighbors.keys():
                neighbours = [index]
                neighbours += spatial_weights.neighbors[index]

                values_list = data.loc[neighbours]

                if rng:
                    values_list = limit_range(values_list, rng=rng)
                results_list.append(Theil(values_list).T)
            else:
                results_list.append(np.nan)

        self.series = pd.Series(results_list, index=gdf.index)
예제 #5
0
    def __init__(self, gdf, values, spatial_weights, unique_id, rng=None):
        try:
            from inequality.theil import Theil
        except ImportError:
            try:
                from pysal.explore.inequality.theil import Theil
            except ImportError:
                raise ImportError("The 'inequality' or 'pysal' package is required.")

        self.gdf = gdf
        self.sw = spatial_weights
        self.id = gdf[unique_id]
        self.rng = rng

        data = gdf.copy()
        if values is not None:
            if not isinstance(values, str):
                data["mm_v"] = values
                values = "mm_v"
        self.values = data[values]

        data = data.set_index(unique_id)

        results_list = []
        for index, row in tqdm(data.iterrows(), total=data.shape[0]):
            neighbours = spatial_weights.neighbors[index].copy()
            if neighbours:
                neighbours.append(index)
            else:
                neighbours = [index]

            values_list = data.loc[neighbours][values]

            if rng:
                from momepy import limit_range

                values_list = limit_range(values_list, rng=rng)
            results_list.append(Theil(values_list).T)

        self.series = pd.Series(results_list, index=gdf.index)
예제 #6
0
    def __init__(
        self,
        gdf,
        values,
        spatial_weights,
        unique_id,
        rng=None,
        mode="all",
        verbose=True,
    ):
        self.gdf = gdf
        self.sw = spatial_weights
        self.id = gdf[unique_id]
        self.rng = rng
        self.modes = mode

        if rng:
            from momepy import limit_range

        data = gdf.copy()
        if values is not None:
            if not isinstance(values, str):
                data["mm_v"] = values
                values = "mm_v"
        self.values = data[values]

        data = data.set_index(unique_id)[values]

        means = []
        medians = []
        modes = []

        allowed = ["mean", "median", "mode"]

        if mode == "all":
            mode = allowed
        elif isinstance(mode, list):
            for m in mode:
                if m not in allowed:
                    raise ValueError(
                        "{} is not supported as mode.".format(mode))
        elif isinstance(mode, str):
            if mode not in allowed:
                raise ValueError("{} is not supported as mode.".format(mode))
            mode = [mode]

        for index in tqdm(data.index, total=data.shape[0],
                          disable=not verbose):
            if index in spatial_weights.neighbors.keys():
                neighbours = [index]
                neighbours += spatial_weights.neighbors[index]

                values_list = data.loc[neighbours]

                if rng:
                    values_list = limit_range(values_list, rng=rng)
                if "mean" in mode:
                    means.append(np.mean(values_list))
                if "median" in mode:
                    medians.append(np.median(values_list))
                if "mode" in mode:
                    modes.append(sp.stats.mode(values_list)[0][0])

            else:
                if "mean" in mode:
                    means.append(np.nan)
                if "median" in mode:
                    medians.append(np.nan)
                if "mode" in mode:
                    modes.append(np.nan)

        if "mean" in mode:
            self.series = self.mean = pd.Series(means, index=gdf.index)
        if "median" in mode:
            self.median = pd.Series(medians, index=gdf.index)
        if "mode" in mode:
            self.mode = pd.Series(modes, index=gdf.index)
예제 #7
0
파일: test_utils.py 프로젝트: ljwolf/momepy
 def test_limit_range(self):
     assert mm.limit_range(range(10), rng=(25, 75)) == [3, 4, 5, 6]
     assert mm.limit_range(range(10),
                           rng=(10, 90)) == [1, 2, 3, 4, 5, 6, 7, 8]
예제 #8
0
파일: diversity.py 프로젝트: ljwolf/momepy
def theil(objects, values, spatial_weights=None, order=None, rng=(0, 100)):
    """
    Calculates the Theil measure of inequality of values within k steps of morphological tessellation

    Uses `pysal.explore.inequality.theil.Theil` under the hood.

    .. math::


    Parameters
    ----------
    objects : GeoDataFrame
        GeoDataFrame containing morphological tessellation
    values : str, list, np.array, pd.Series
        the name of the dataframe column, np.array, or pd.Series where is stored character value.
    spatial_weights : libpysal.weights, optional
        spatial weights matrix - If None, Queen contiguity matrix of set order will be calculated
        based on objects.
    order : int
        order of Queen contiguity
    rng : Two-element sequence containing floats in range of [0,100], optional
        Percentiles over which to compute the range. Each must be
        between 0 and 100, inclusive. The order of the elements is not important.

    Returns
    -------
    Series
        Series containing resulting values.

    References
    ----------

    Examples
    --------

    """
    from pysal.explore.inequality.theil import Theil
    # define empty list for results
    results_list = []

    print('Calculating Theil index...')

    if spatial_weights is None:
        print('Generating weights matrix (Queen) of {} topological steps...'.format(order))
        from momepy import Queen_higher
        # matrix to define area of analysis (more steps)
        spatial_weights = Queen_higher(k=order, geodataframe=objects)
    else:
        if not all(objects.index == range(len(objects))):
            raise ValueError('Index is not consecutive range 0:x, spatial weights will not match objects.')

    if values is not None:
        if not isinstance(values, str):
            objects['mm_v'] = values
            values = 'mm_v'

    for index, row in tqdm(objects.iterrows(), total=objects.shape[0]):
        neighbours = spatial_weights.neighbors[index]
        values_list = objects.iloc[neighbours][values].tolist()
        if values_list:
            values_list.append(row[values])
        else:
            values_list = [row[values]]

        if rng:
            from momepy import limit_range
            values_list = limit_range(values_list, rng=rng)
        results_list.append(Theil(values_list).T)

    series = pd.Series(results_list)

    if 'mm_v' in objects.columns:
        objects.drop(columns=['mm_v'], inplace=True)

    print('Theil index calculated.')
    return series