示例#1
0
def append_column_to_array(array, new_column, new_values, other_cols=None):
    """
    Adds a new column to a record array

    Parameters
    ----------
    array : numpy record array
    new_column : str
        The name of the new column to be created
    new_values : scalar or sequence
        The value or array of values to be inserted into the new column.
    other_cols : sequence of str, optional
        A subset of exististing columns that will be kept in the final
        array. If not provided, all existing columns are retained.

    Returns
    -------
    new_array : numpy record array
        The new array with the new column.

    """

    from numpy.lib.recfunctions import append_fields

    # validate and convert the new column to a list to work
    # with the numpy API
    new_column = validate.non_empty_list(new_column)

    # validate and select out all of the "other" columns
    if other_cols is not None:
        other_cols = validate.non_empty_list(other_cols)
        if new_column in other_cols:
            msg = "`new_column` can not be the name of an existing column."
            raise ValueError(msg)
        else:
            # this raises a nasty warning in numpy even though this is the
            # way the warning says we should do this:
            with warnings.catch_warnings(record=True) as w:  # pragma: no cover
                warnings.simplefilter("ignore")
                array = array[other_cols].copy()

                # make sure we don't have any unicode column names
                col_names = numpy.array(array.dtype.names)
                array.dtype.names = [
                    cn.encode('ascii', 'ignore') for cn in col_names
                ]

    # convert the new value to an array if necessary
    if numpy.isscalar(new_values):
        new_values = numpy.array([new_values] * array.shape[0])

    # append the new colum
    new_array = append_fields(array, new_column, [new_values])

    return new_array.data
示例#2
0
    def analyze(self, **params):
        """ Propagates water quality scores from monitoring locations
        to upstream subcatchments. Calls directly to :func:`propagate`.
        """

        # analysis options
        ws = params.pop('workspace', '.')
        overwrite = params.pop('overwrite', True)
        add_output_to_map = params.pop('add_output_to_map', False)
        output_layer = params.pop('output_layer', None)

        # subcatchment info
        sc = params.pop('subcatchments', None)
        ID_col = params.pop('ID_column', None)
        downstream_ID_col = params.pop('downstream_ID_column', None)

        # monitoring location info
        ml = params.pop('monitoring_locations', None)
        ml_type_col = params.pop('ml_type_col', None)
        included_ml_types = validate.non_empty_list(params.pop(
            'included_ml_types', None),
                                                    on_fail='create')

        # monitoring location type filter function
        if ml_type_col is not None and len(included_ml_types) > 0:
            ml_filter = lambda row: row[ml_type_col] in included_ml_types
        else:
            ml_filter = None

        # value columns and aggregations
        value_cols_string = params.pop('value_columns', None)
        value_columns = [
            vc.split(' ')
            for vc in value_cols_string.replace(' #', ' average').split(';')
        ]

        # streams data
        streams = params.pop('streams', None)

        # perform the analysis
        with utils.WorkSpace(ws), utils.OverwriteState(overwrite):
            output_layers = propagate(
                subcatchments=sc,
                id_col=ID_col,
                ds_col=downstream_ID_col,
                monitoring_locations=ml,
                ml_filter=ml_filter,
                ml_filter_cols=ml_type_col,
                value_columns=value_columns,
                output_path=output_layer,
                streams=streams,
                verbose=True,
                asMessage=True,
            )

            if add_output_to_map:
                for lyr in output_layers:
                    self._add_to_map(lyr)

        return output_layers
示例#3
0
def populate_field(table, value_fxn, valuefield, keyfields=None):
    """
    Loops through the records of a table and populates the value of one
    field (`valuefield`) based on another field (`keyfield`) by passing
    the entire row through a function (`value_fxn`).

    Relies on `arcpy.da.UpdateCursor`_.

    .. _arcpy.da.UpdateCursor: http://goo.gl/sa3mW6

    Parameters
    ----------
    table : Layer, table, or file path
        This is the layer/file that will have a new field created.
    value_fxn : callable
        Any function that accepts a row from an `arcpy.da.SearchCursor`
        and returns a *single* value.
    valuefield : string
        The name of the field to be computed.
    keyfields : list of str, optional
        The other fields that need to be present in the rows of the
        cursor.

    Returns
    -------
    None

    .. note::
       In the row object, the `valuefield` will be the last item.
       In other words, `row[0]` will return the first values in
       `*keyfields` and `row[-1]` will return the existing value of
       `valuefield` in that row.

    Examples
    --------
    >>> # populate field ("Company") with a constant value ("Geosyntec")
    >>> populate_field("wetlands.shp", lambda row: "Geosyntec", "Company")

    """

    fields = validate.non_empty_list(keyfields, on_fail='create')
    fields.append(valuefield)
    check_fields(table, *fields, should_exist=True)

    with arcpy.da.UpdateCursor(table, fields) as cur:
        for row in cur:
            row[-1] = value_fxn(row)
            cur.updateRow(row)
示例#4
0
def aggregate_geom(layerpath,
                   by_fields,
                   field_stat_tuples,
                   outputpath=None,
                   **kwargs):
    """
    Aggregates features class geometries into multipart geometries
    based on columns in attributes table. Basically this is a groupby
    operation on the attribute table, and the geometries are simply
    combined for aggregation. Other fields can but statistically
    aggregated as well.

    Parameters
    ----------
    layerpath : str
        Name of the input feature class.
    by_fields : list of str
        The fields in the attribute table on which the records will be
        aggregated.
    field_stat_tuples : list of tuples of str
        List of two-tuples where the first element element is a field
        in the atrribute and the second element is how that column
        should be aggreated.

        .. note ::

           Statistics that are available are limited to those supported
           by `arcpy.management.Dissolve`. Those are: "FIRST", "LAST",
           "SUM", "MEAN", "MIN", "MAX", "RANGE", "STD", and "COUNT".

    outputpath : str, optional
        Name of the new feature class where the output should be saved.
    **kwargs
        Additional parameters passed to `arcpy.management.Dissolve.

    Returns
    -------
    outputpath : str, optional
        Name of the new feature class where the output was sucessfully
        saved.

    Examples
    --------
    >>> from propagator import utils
    >>> with utils.WorkSpace('C:/SOC/data.gdb'):
    ...     utils.aggregate_geom(
    ...         layerpath='streams_with_WQ_scores',
    ...         by_fields=['Catch_ID', 'DS_Catch_ID'],
    ...         field_stat_tuples=[('Dry_Metals', 'max'), ('Wet_Metals', 'min')],
    ...         outputpath='agg_streams'
    ...     )

    """

    by_fields = validate.non_empty_list(by_fields)
    arcpy.management.Dissolve(in_features=layerpath,
                              out_feature_class=outputpath,
                              dissolve_field=by_fields,
                              statistics_fields=field_stat_tuples,
                              **kwargs)

    return outputpath
 def test_empty_creates(self):
     nt.assert_list_equal(validate.non_empty_list([], on_fail='create'), [])
 def test_empty_list_raises(self):
     validate.non_empty_list([])
 def test_None_raises(self):
     validate.non_empty_list(None)
 def test_scalar(self):
     x = 1
     nt.assert_list_equal(validate.non_empty_list(x), [x])
 def test_baseline(self):
     x = [1, 2, 3]
     nt.assert_list_equal(validate.non_empty_list(x), x)