Select to view content in your preferred language

add time constraint to near tool

6241
18
Jump to solution
04-08-2015 08:30 AM
QiuhuaMa
New Contributor II

Hi,

I am working on my dissertation right now and need to use Arcgis to calculate the distance from the nearest fire to each house.

Since fire is polygon and house is point, I just use near tool to calculate distance from the nearest fire to the house. However the fires I am interested in is the fire that burned within the past 7 years before the sale of the homes. So I need to exclude all fires that burned after the sale date of the home, and all fires that burned greater than seven years before the sale of the home.

Is there anyway to add a time constraint to near tool using python? 

thanks,

chelsea

0 Kudos
18 Replies
XanderBakker
Esri Esteemed Contributor

If you consider that a reply answered your question, please mark that reply as the correct answer. See: Mark a reply as the Correct Answer

0 Kudos
QiuhuaMa
New Contributor II

I tried this code with another house sale data. This data has different

fields from the one I posted, but still has house id and sale date. I got

the following message:

Runtime error

Traceback (most recent call last):

File "", line 36, in addField

File "c:\program files (x86)\arcgis\desktop10.1\arcpy\arcpy\__init__.py",

line 1075, in ListFields

return gp.listFields(dataset, wild_card, field_type)

File "c:\program files

(x86)\arcgis\desktop10.1\arcpy\arcpy\geoprocessing\_base.py", line 344, in

listFields

self._gp.ListFields(*gp_fixargs(args, True)))

IOError: "C:\Forum\DistFireHouse\shp\housesaledata.shp" does not exist

any idea what happened?

Chelsea

0 Kudos
QiuhuaMa
New Contributor II

I just corrected this error: IOError:

"C:\Forum\DistFireHouse\shp\housesaledata.shp"

does not exist

but still got the message:

Runtime error

Traceback (most recent call last):

File "", line 74, in chkDate

File

"C:\Python27\ArcGIS10.1\lib\site-packages\dateutil\relativedelta.py", line

247, in __radd__

raise TypeError, "unsupported type for add operation"

TypeError: unsupported type for add operation

0 Kudos
XanderBakker
Esri Esteemed Contributor

Glad to hear that you solved to error referring to the shapefile that was being referenced.

The other error on line 74 in the chkDate function refers to this line:

date_2monthsbefore_sale = date_sale + relativedelta(months=-2)

The only variable that could influence the error is the date_sale. Are you sure that the date field in the houses is of type Date? Could you check that all records have valid values?

0 Kudos
QiuhuaMa
New Contributor II

Yeah, the problem is some houses don't have a valid sale date! After

deleting these data, it works.

thanks,

Chelsea

0 Kudos
XanderBakker
Esri Esteemed Contributor

Glad it works. Better code would include methods to properly handle those cases...

0 Kudos
QiuhuaMa
New Contributor II

Hi,

another way to examine the effect of fire on house price is to check number

and size of fire within a certain distance in the last 7 years.

I would like to count number of fires within 5km of a house in the past 7

years, then calculate their

average size!

Can this be done using python?

THANKS SO MUCH,

chelsea

2015年4月10日 下午5:25于 "Xander Bakker" <geonet@esri.com>写道:

GeoNet

<http://jiveon.jivesoftware.com/wf/click?upn=Dg1s4x8le7Lmxv8KWGaqo8h7SGfRSMkw-2FpvHGF9-2FW3rK-2Bvs1kL9-2FnG6jjf2NZhrLDz0M-2BrY-2By9IaziQEKVk3Hg-3D-3D_cklnSfGWc0xtrUWz22hpfRmL-2BltIn2gVqEZxa2WpZ5WxnKfgSyyLU2hOb5I9HulWredg8bzBclHT-2Bssd3ileiOvLFQa-2FmBCtTaSqDGUHKu4XnPDXbl4Ut-2FMsay6tDfBzbVyLltMUwOlSIVVR-2BV5NMQcQfabq6bnsJ3h2e1w1qxNeHuvAFqXMl-2Fgn3Jq-2FWu3P1S-2FUEe4CHuJjCedZY-2BH76WvpBn6acAcWT4wYCAVAPnSBQ3MG2e01gVAgY-2FP54joxFx3SrBDvBPCJclBcl-2B3JuMZQtE3dW34Cm4Y7KaLDVIyvFkRba7LQTlzH6ZiELIuu> add

time constraint to near tool

reply from Xander Bakker

<http://jiveon.jivesoftware.com/wf/click?upn=Dg1s4x8le7Lmxv8KWGaqo7A4BXwO9PY1WvQ5cXCtK4-2FJIS3CK9JWidf-2FyI744iulp2nFUojYk8SjUF04OfNOXam6B1F7Qh0-2B9QYrDAA5RTM-3D_cklnSfGWc0xtrUWz22hpfRmL-2BltIn2gVqEZxa2WpZ5WxnKfgSyyLU2hOb5I9HulWredg8bzBclHT-2Bssd3ileiOvLFQa-2FmBCtTaSqDGUHKu4XnPDXbl4Ut-2FMsay6tDfBzYMfGzF0tzxGItU0XBAVRvIFK1Crre-2BQMAzijTGJvPtjjVYP9Y2zQdaiYRPZQVTXdLWrglYoGLlp7tj9o4J8kB32EMk-2BdykdvaaHciSVPu0coHhC9yF25LKcHvkBr1y2gAnZn7Nufsz3QlcJ-2Fmb-2BV9l9nGGoVsfujd2BJdCilzosqp8OjRNjyb4CuZDTW9M7-2F>

in Python - View the full discussion

<http://jiveon.jivesoftware.com/wf/click?upn=Dg1s4x8le7Lmxv8KWGaqo0VQjeJBYpG9HGC8QZBT-2FEx1rLkR8-2Fx-2FWdOrqbWRfYSj-2Bj-2F8IDaEgj29-2BmPV8A-2By0H03mtjLHTpxxgI2CO1cdwQ-3D_cklnSfGWc0xtrUWz22hpfRmL-2BltIn2gVqEZxa2WpZ5WxnKfgSyyLU2hOb5I9HulWredg8bzBclHT-2Bssd3ileiOvLFQa-2FmBCtTaSqDGUHKu4XnPDXbl4Ut-2FMsay6tDfBzmKBKWVY715nrdJfp-2FROf-2BiJjyGh0EpaBnitt8dOcfj8-2FIpvsZkweBZlgU8P46bbtoaUsygjnX-2Bj83goL3QHpLVW5CqZCUL-2Fv0eXXfNhrRuQ5TpEhowkCZPUIt9zUhX6lNio2ms1y3ULw3lXOtWDOOXPhz7pltNlXOR9jdHaCaabEZ8BTMt899G3wLZUdw7oA>

0 Kudos
XanderBakker
Esri Esteemed Contributor

Yes, this can be done. The logic should go in the lines 65 - 70. Instead of checking the distance you could determine the number of fire, min, max and mean size and pass this back.

You would need to change to the way the result is read on line 31 and add the appropriate fields to store the results. Lines 13 to 23. It may be good to open a new discussion and add a link to this discussion, since this one is getting a little long...

0 Kudos
XanderBakker
Esri Esteemed Contributor

Since it may be a little difficult to verify the result I threw in another piece of code to aid the verification process:

Connections.png

These are lines that connect each house with the nearest fire and add the date info to the lines for verification.

  • FireDate is the date of the fire
  • ma_date_dt is the date when the house was sold
  • YrSaleMn7 is the year of sale minus 7 years
  • SaleMin2m is the date two months before the house was sold
  • The FireOID can be used to join additional data from the fire polygons to the lines (use the FID of the fire polygons)
  • The parcelid provides the link to the houses.

What you need to do is change these lines in the code below:

  • reference the input shapefiles on line 10 and 11
  • define the output shapefile on line 23

Run the code below:

import arcpy
import os
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta

def main():
    arcpy.env.overwriteOutput = True

    # input fc's
    fc_house = r"C:\Forum\DistFireHouse\shp\housesaledata.shp"
    fc_fire = r"C:\Forum\DistFireHouse\shp\firehistory_NAD_fips3002_feet.shp"


    # input field house
    fld_fire_oid = "FireOID"
    fld_parcel_id = "parcelid"
    fld_date_sale = "ma_date_dt"

    # input fields fires
    fld_oid_fire = arcpy.Describe(fc_fire).OIDFieldName

    # output fc
    fc_out = r"C:\Forum\DistFireHouse\shp\lines01.shp"

    # output fields (parcelid, double)
    fld_sale_min7 = "YrSaleMin7"
    fld_sale_2month = "SaleMin2m"
    fld_fire_date = "FireDate"
    fld_dist = "Dist2Fire"

    # create empty output fc
    sr = arcpy.Describe(fc_house).spatialReference
    shp_folder, shp_name = os.path.split(fc_out)
    arcpy.CreateFeatureclass_management(shp_folder, shp_name, "POLYLINE", spatial_reference=sr)

    # add output fields
    addField(fc_out, fld_parcel_id, "DOUBLE")
    addField(fc_out, fld_fire_oid, "LONG")
    addField(fc_out, fld_date_sale, "DATE")
    addField(fc_out, fld_fire_date, "DATE")
    addField(fc_out, fld_sale_min7, "INTEGER")
    addField(fc_out, fld_sale_2month, "DATE")
    addField(fc_out, fld_dist, "DOUBLE")

    # loop through houses
    cnt = 0
    flds_out = ("SHAPE@", fld_parcel_id, fld_fire_oid, fld_date_sale,
                fld_fire_date, fld_sale_min7, fld_sale_2month, fld_dist)
    flds_house = ("SHAPE@", fld_parcel_id, fld_date_sale, fld_fire_oid)
    with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:
        with arcpy.da.SearchCursor(fc_house, flds_house) as curs_in:
            for row_in in curs_in:
                cnt += 1
                if cnt % 25 == 0:
                    print "Processing connection: {0}".format(cnt)
                pnt1 = row_in[0]
                parcel_id = row_in[1]
                date_sale = row_in[2]
                fire_oid = row_in[3]

                # get fire details
                pnt2, date_fire = getDetailsFirePolygon(fc_fire, fld_oid_fire, fire_oid, pnt1)

                # create the lines
                line = arcpy.Polyline(arcpy.Array([pnt1.firstPoint, pnt2.firstPoint]), sr)

                date_2monthsbefore_sale = date_sale + relativedelta(months=-2)
                year_salemin7 = date_sale.year - 7

                row_out = (line, parcel_id, fire_oid, date_sale, date_fire,
                           year_salemin7, date_2monthsbefore_sale, line.length, )
                curs_out.insertRow(row_out)


def getDetailsFirePolygon(fc_fire, fld_oid_fire, fire_oid, pnt):
    fld_year = "FIRE_YEAR"
    fld_month = "FIRE_MONTH"
    fld_day = "FIRE_DAY"

    where = "{0} = {1}".format(arcpy.AddFieldDelimiters(fc_fire, fld_oid_fire), fire_oid)
    row = arcpy.da.SearchCursor(fc_fire, ("SHAPE@", fld_year, fld_month, fld_day), where_clause=where).next()
    polygon = row[0]
    year_fire = int(row[1])
    try:
        month_fire = int(row[2])
    except:
        month_fire = 6
    try:
        day_fire = int(row[3])
    except:
        day_fire = 15

    date_fire = datetime(year=year_fire, month=month_fire, day=day_fire)

    polyline = polygon.boundary()
    pnt2 = polyline.queryPointAndDistance(pnt, False)[0]

    del row
    return pnt2, date_fire

def addField(fc, fldname, fldtype):
    if len(arcpy.ListFields(fc, wild_card=fldname)) == 0:
        arcpy.AddField_management(fc, fldname, fldtype)

if __name__ == '__main__':
    main()

Add the result to ArcMap and define two relates on the lines featureclass:

  • one linking the lines to the houses using the parcelid fields
  • the other linking the lines to the fires using the Fireoid and FID fields