Creating defined lists

698
4
11-07-2016 12:00 PM
KevinWyckoff2
New Contributor

I want to create a script that will help me sort a feature class of 7000 features into blocks of 60 features. The features would stay in the same feature class, just have a value added to a field delineating the different groups. I understand what needs to be done, but am completely stumped on where to start looking for help.

Tags (3)
0 Kudos
4 Replies
JoshuaBixby
MVP Esteemed Contributor

How do you want the groups defined or grouped together?  For example, do you want OIDs 1-60 to be Group 1/A, OIDs 61-120 to be Group 2/B, etc...  Or, is there some other grouping you want to implement?

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

If you just want to group the first 60 items into group 1, the second 60 items into group 2, the third 60 items into group 3, etc... then the following should work:

fc =       # path to feature class
block_id = # name of field to populate block id/code
with arcpy.da.UpdateCursor(fc,
                           block_id,
                           sql_clause(None, "ORDER BY ObjectID") as cur:
    for i, _ in enumerate(cur):
        cur.updateRow([i//60 + 1])‍‍‍‍‍‍‍‍‍‍‍‍‍‍
DanPatterson_Retired
MVP Esteemed Contributor

So you want to produce a uniform distribution of group numbers to which to assign each feature?  If so, then look at the following demonstration of using the random.uniform distribution

>>> z = np.random.randint(1,7, 60000)
>>> bins = np.arange(1,8)
>>> h = np.histogram(z, bins)
>>> h
(array([10046, 10078,  9922,  9936, 10094,  9924]), array([1, 2, 3, 4, 5, 6, 7]))
‍‍‍‍‍

so the result of the above is 6 groups numbered 1 to 6 inclusive with about 10,000 in each group.

If you need exactly the same number in each group, then that can be done, by producing a range of numbers, repeating it, then shuffling it... for example

PS, I should add that you could produce a table with the results of either and simply join it to the source table or in the case of randint, you can do that in the field calculator... random.shuffle will require a join since the distribution needs to be produced first.  The table case, requires an ID field and the values, to facilitate the join.

>>> vals = np.arange(1,7)
>>> z = np.repeat(vals,10000)
>>> np.random.shuffle(z)
>>> z[:60]
array([1, 5, 4, 1, 6, 6, 3, 3, 4, 2, 1, 3, 1, 6, 3, 6, 1, 6, 3, 6, 3, 4, 5, 1,
       1, 1, 2, 1, 3, 4, 4, 5, 4, 2, 4, 2, 6, 3, 4, 6, 3, 6, 6, 1, 6, 5, 3, 4,
       2, 6, 6, 3, 2, 3, 1, 3, 5, 6, 2, 4])
>>> h = np.histogram(z, np.arange(1,8))
>>> h
(array([10000, 10000, 10000, 10000, 10000, 10000]), array([1, 2, 3, 4, 5, 6, 7]))
‍‍‍‍‍‍‍‍‍‍
DanPatterson_Retired
MVP Esteemed Contributor

Of course you can produce the array then export it to a table using

NumPyArrayToTable—Help | ArcGIS for Desktop 

A sample of the prodecure to produce 70 numbers each with a frequency of 10, shuffled so they are in random order...

>>> import numpy as np
>>> vals = np.arange(1,7)
>>> z = np.repeat(vals,10)
>>> np.random.shuffle(z)
>>> ID = np.arange(70)
>>> tbl = np.array(list(zip(ID,z)), dtype = [('ID', 'int'), ('Class', 'int')])
>>> tbl
array([(0, 4), (1, 1), (2, 3), (3, 2), (4, 6), (5, 6), (6, 5), (7, 2), (8, 6),
       (9, 6), (10, 3), (11, 3), (12, 1), (13, 5), (14, 2), (15, 6), (16, 5),
       (17, 3), (18, 6), (19, 2), (20, 4), (21, 5), (22, 2), (23, 2), (24, 3),
       (25, 1), (26, 1), (27, 2), (28, 2), (29, 1), (30, 5), (31, 6), (32, 4),
       (33, 5), (34, 3), (35, 4), (36, 4), (37, 1), (38, 4), (39, 4), (40, 6),
       (41, 5), (42, 3), (43, 3), (44, 6), (45, 1), (46, 5), (47, 2), (48, 3),
       (49, 1), (50, 5), (51, 6), (52, 2), (53, 3), (54, 1), (55, 4), (56, 4),
       (57, 5), (58, 4), (59, 1)], 
      dtype=[('ID', '<i8'), ('Class', '<i8')])
>>> #then use NumPyArrayToTable to get your table

Then you can save it as a table and join the ID field to the FID or OBJECTID field as appropriate

0 Kudos