1

I have a dataset that contains a field with a range of numbers (e.g. 1, 2, 3-6) as well as other fields. I've used python to expand the range field into discrete numbers (e.g. 1, 2, 3, 4, 5, 6) stored in a list in python. I would like to insert rows (6 in this example) with the range values. The values from the other fields would be copied for each new row, for each row in the table.

Row Example

| A | 1, 2, 3-6 | xxa | xxb |

to

| A | 1 | xxa | xxb |
| A | 2 | xxa | xxb |
| A | 3 | xxa | xxb |
| A | 4 | xxa | xxb |
| A | 5 | xxa | xxb |
| A | 6 | xxa | xxb |

I have adapted the code written by @Aaron. The code below works for the first row, but I would like it to read every row in the input table. In other words, it is not advancing throughout the table. I think I need to add another for loop at the beginning of insert_rows().

# import libraries
import arcpy
import os
arcpy.env.overwriteOutput = True
tbl = arcpy.GetParameterAsText(0)
def extractit(str):
 """
 Creates a list (e.g. [1,2,3,4,5,6] from string such as '1, 2, 3-6'
 """
 parts = str.replace(" ", "").split(",")
 numbers = []
 for part in parts:
 if '-' in part:
 p = part.split("-")
 numbers.extend(list(range(int(p[0]), int(p[1]) + 1)))
 else:
 numbers.append(int(part))
 return numbers
def create_table(tbl):
 """
 Creates a duplicate (but empty) table
 because we do not want to alter the original
 """
 arcpy.CreateTable_management(os.path.dirname(tbl), os.path.basename(tbl) + "_altered_v2", template=tbl)
 arcpy.DeleteRows_management(tbl + "_altered_v2")
def insert_rows(tbl):
 """
 Insert rows into new table
 """
 # Get row value in original table
 row = [row for row in arcpy.da.SearchCursor(tbl, ["MERIDIAN", "TOWNSHIP", "RANGE", "TOWNSHIP_D", "RANGE_D",
 "SUBDIVIS", "NOTES_SU",
 "BLMSERIA", "CATEGORY", "ACREAGE", "EXCLUSIO", "VILL_BLK",
 "CONV_DAT", "IC_PAT_N", "ENCUMBRA"])][0]
 numbers = extractit(row[5]) # Extract number field
 cursor = arcpy.da.InsertCursor(tbl + "_altered_v2", ["MERIDIAN", "TOWNSHIP", "RANGE", "TOWNSHIP_D", "RANGE_D",
 "SUBDIVIS", "NOTES_SU",
 "BLMSERIA", "CATEGORY", "ACREAGE", "EXCLUSIO", "VILL_BLK",
 "CONV_DAT", "IC_PAT_N", "ENCUMBRA"])
 for number in numbers:
 row_value = (row[0], row[1], row[2], row[3], row[4], str(number), row[6], row[7], row[8], row[9], row[10],
 row[11], row[12], row[13], row[14])
 cursor.insertRow(row_value)
 # Delete cursor object
 del cursor
if __name__ == '__main__':
 create_table(tbl)
 insert_rows(tbl)
PolyGeo
65.5k29 gold badges115 silver badges349 bronze badges
asked Mar 14, 2019 at 1:07
4
  • 1
    Are you wanting to duplicate the geometry in your first example so that one feature becomes six? Commented Mar 14, 2019 at 2:09
  • 1
    That's how I read it @Aaron.. I would do this from a source to a destination shapefile (use arcpy.Select_analysis(InPoints,OutPoints,'FID=(FID+1)') to create an empty shapefile with the same CRS and fields) with a dreaded double cursor (arcpy.da.SeachCursor(InPoints,'*') and arcpy.da.InsertCursor(OutPoints,'*') copy all other values and change the specific value for each in the list and then insertRow.. just remember that the shape needs to be unpacked then packed again because it belongs to a different feature class. Commented Mar 14, 2019 at 4:37
  • @MichaelStimson Agreed, it is a good practice to create a dupe feature class. Commented Mar 14, 2019 at 4:45
  • I changed the code to meet your requirements. Like you indicated, it only required a for loop. Commented Mar 14, 2019 at 23:36

1 Answer 1

2

Here is one approach. There are three main components:

  1. extractit() manipulates unruly strings such as '1, 2, 3-6'
  2. create_fc() creates a new featureclass so as not to alter the original
  3. insert_rows() puts all the pieces together

import arcpy, os
fc = r'C:\temp\test.gdb\temp'
def extractit(str):
 """
 Creates a list from string such as '1, 2, 3-6'
 """
 parts = str.replace(" ", "").split(",")
 numbers = []
 for part in parts:
 if '-' in part:
 p = part.split("-")
 numbers.extend(list(range(int(p[0]), int(p[1]) + 1)))
 else:
 numbers.append(int(part))
 return numbers
def create_fc(fc):
 # Create a new featureclass
 arcpy.CreateFeatureclass_management(os.path.dirname(fc), os.path.basename(fc) + "_altered", template = fc, spatial_reference = fc)
 # Delete Rows
 arcpy.DeleteRows_management(fc + "_altered")
def insert_rows(fc):
 # Get row value in original fc
 rows =[row for row in arcpy.da.SearchCursor(fc, ["field1", "field2", "field3", "field4", "SHAPE@"])]
 for row in rows:
 numbers = extractit(row[1]) # Extract number field
 cursor = arcpy.da.InsertCursor(fc + "_altered", ["field1", "field2", "field3", "field4", "SHAPE@"])
 for number in numbers:
 row_value = (row[0], str(number), row[2], row[3], row[4])
 cursor.insertRow(row_value)
 # Delete cursor object
 del cursor
if __name__ == '__main__':
 create_fc(fc)
 insert_rows(fc)

Before

enter image description here

After

enter image description here

answered Mar 14, 2019 at 4:42
1
  • 1
    Spectacular! There's a few very good pearls of wisdom in that code. Commented Mar 14, 2019 at 5:28

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.