Combining polygons by date fields

4353
21
Jump to solution
08-12-2014 07:54 AM
deleted-user-_78mlgGtbbzB
New Contributor II

I have an interesting problem.  I have been asked to create a set of polygons using dates.  Below is an example table showing the data.  As you can see the table is sorted by start year.

 

What I have to do is generate a set of polygons each time the start year, month and day changes.  So the first polygon will just contain the first row of data.  The second polygon will contain both the first and second and so on.

 

There is also another element to this.  Each row of data has an end year, month and day.  If a row has an end year of 2300 then that row will stay in the output once it has been added.  If there is an end year that does not equal 2300 then that row will not be included in future versions of the output.

 

data.jpg

So is there anyone who can help?  I have about two hundred tables like the one above. Would like a model builder solution.

 

Thanks in anticipation.

 

Paul

0 Kudos
21 Replies
deleted-user-_78mlgGtbbzB
New Contributor II

Hi Xander,

Thank you so much.  It now does what I want it to do.  You are a star.

Many thanks

Paul

0 Kudos
DanPatterson_Retired
MVP Emeritus

Please then, mark one of Xander's answers as correct...currently the thread is still open

0 Kudos
deleted-user-_78mlgGtbbzB
New Contributor II

Hi Dan,

Sorry, how do I do that?

Thanks

Paul

0 Kudos
DanPatterson_Retired
MVP Emeritus

for each thread there should be a greenish star with test beside it saying "correct answer"  click on it for the thread that answered your question and NOT this one

0 Kudos
XanderBakker
Esri Esteemed Contributor

I'm glad it worked for you. Good luck!

0 Kudos
deleted-user-_78mlgGtbbzB
New Contributor II

Hi Xander,

Just one more thing.  How can I use your script to run against multiple input shapefiles?

Thanks

Paul

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Paul,

That is possible, but it might be necessary to know a little more on the folder structure where you have your input featureclasses and how you want to name the outputs.

Normally a arcpy.ListFeatureclasses() can be used to get a list of featureclasses in the current workspace. In case they are in multiple folders and sub folders the arcpy.da.Walk() is better. Based on the input name, you can create an outputname (like for instance inputname_merged).

The current script can be rewritten as a function to process a single featureclass. This function will be called from the loop through the input featureclasses.

Kind regards, Xander

0 Kudos
deleted-user-_78mlgGtbbzB
New Contributor II

Hi Xander,

Thanks for the reply.

My shapefiles are currently in this folder C:\Users\PaulBritten\Desktop\tenure\All reserves

and the out put name would be as you suggest with the _merged at the end of the name.

I will admit that I am not a python expert at all and have no idea how to amend/update the python script with any new functionality. Therefore would you mind amending your script?

Many thanks and sorry to be such a pain.

Paul

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Paul,

Don't worry, that what the forum is all about... to help one another.

Have a look at the code below. The majority is placed inside a function "MergePolygonsOnDate". The main function (lines 13 - 23) contains the logic for looping through your featureclasses. It will create a list of all the featureclasses in you workspace. Based on the input name it will create the new output names. On line 23 for each featureclass the "MergePolygonsOnDate" is called. I haven't tested the code, so if you run into problems, just post it and I'll have a look.

#-------------------------------------------------------------------------------

# Name:        MergePolygonsOnDate_v3.py

# Purpose:     Merge polygons on date range

#

# Author:      xbakker

#

# Created:     19/08/2014

#-------------------------------------------------------------------------------

import arcpy, os

from datetime import datetime, timedelta

def main():

    # specify the workspace

    ws = r"C:\Users\PaulBritten\Desktop\tenure\All reserves"

    arcpy.env.workspace = ws

    arcpy.env.overwriteOutput = True

    lst_fc = arcpy.ListFeatureClasses()

    for fc in lst_fc:

        name, ext = os.path.splitext(fc)

        fc_out = "{0}_merged{1}".format(name, ext)

        MergePolygonsOnDate(os.path.join(ws, fc), os.path.join(ws, fc_out))

def MergePolygonsOnDate(fc, fc_out):

    # change settings

    fld_start = "DateFrom" # create date field and fill it with content of StartDate

    fld_end = "DateTo" # create date field and fill it with content of EndDate

    fld_name = "Name"

    fld_outname = "OutputName" # output name

    len_outname = 75

    # create empty output shapefile

    ws_path, fc_out_name = os.path.split(fc_out)

    arcpy.CreateFeatureclass_management(ws_path, fc_out_name,

        "POLYGON", fc, "SAME_AS_TEMPLATE", "SAME_AS_TEMPLATE", fc)

    # add string field

    arcpy.AddField_management(fc_out, fld_outname, "TEXT", "", "", len_outname)

    flds = ("SHAPE@", fld_start, fld_end, fld_name)

    flds_out = ("SHAPE@", fld_start, fld_name, fld_outname)

    # create a unique list of dates from start date

    lst_dates = list(set([row[0] for row in arcpy.da.SearchCursor(fc, (fld_start))]))

    lst_dates.sort()

    # insert cursor to store features to new featureclass

    with arcpy.da.InsertCursor(fc_out, (flds_out)) as curs_out:

        # loop through list of unique dates

        for date in lst_dates:

            # create an expression

            expression = "{0} <= date '{2}' AND {1} >= date '{2}'".format(

                arcpy.AddFieldDelimiters(fc, fld_start),

                arcpy.AddFieldDelimiters(fc, fld_end), date)

            i = 0

            # create the searchcursor with the expression

            with arcpy.da.SearchCursor(fc, flds, where_clause=expression) as curs:

                for row in curs:

                    pol = row[0]

                    name = row[3] # take name of first polygon

                    if i == 0:

                        # first polygon is just the polygon"

                        polygon = pol

                    else:

                        # next polygons are added with union

                        polygon = polygon.union(pol)

                    i += 1

                # insert the feature into the output featureclass

                datefrom = date

                i_date = lst_dates.index(date)

                if i_date + 1 > len(lst_dates) - 1:

                    dateto = ""

                    outname = "{0} {1} - {2}".format(name, datefrom.strftime('%Y/%m/%d'), dateto)

                else:

                    dateto = lst_dates[i_date + 1] - timedelta(days=1)

                    outname = "{0} {1} - {2}".format(name, datefrom.strftime('%Y/%m/%d'), dateto.strftime('%Y/%m/%d'))

                curs_out.insertRow((polygon, row[1], name, outname))

if __name__ == '__main__':

    main()

deleted-user-_78mlgGtbbzB
New Contributor II

Hi Xander,

That worked brilliantly.

Many thanks

Paul

0 Kudos