2

I have an attribute table with a date field and a random field. The date field has three different times for each day. I need to input a '1' in the random field for one of those three times in each day.

I created a field that removed the time stamps and just included the day in order to group each day. This is indicated as 'Date' in the code below.

This code sample inputs '1' in he Random column for each of the six time of a random day instead of just one for each day.

import arcpy, random
from arcpy import env
env.workspace = r"H:\Working_Data.gdb"

for fc in arcpy.ListFeatureClasses('*'):

  object_ids = [r[0] for r in arcpy.da.SearchCursor(fc, ['Date'], )]
  sample_size = len(object_ids) / 6
  random_ids = random.sample(object_ids,sample_size)

  with arcpy.da.UpdateCursor(fc, ['Date','Random']) as Cursor:
    for row in Cursor:
        if row[0] in random_ids:
            row[1] = 1
        else:
            row[1] = 0 
        Cursor.updateRow(row)
        print str(row) + 'updating'

I have tried multiple solutions from similar questions but can't get anything to work.

Data:

Date_Time                Date
2003-12-12 1:00:54 AM    2003-12-12
2003-12-12 11:00:54 AM   2003-12-12
2003-12-12 4:02:17 PM    2003-12-12
2003-12-13 1:01:30 AM    2003-12-13
2003-12-13 11:00:24 AM   2003-12-13
2003-12-13 4:00:12 PM    2003-12-13
2003-12-14 1:00:06 AM    2003-12-14
2003-12-14 11:03:11 AM   2003-12-14
2003-12-14 4:00:32 PM    2003-12-14
2003-12-15 1:00:52 AM    2003-12-15
2003-12-15 11:01:54 AM   2003-12-15
2003-12-15 4:01:22 PM    2003-12-15

The output I'm looking for would be something like this where each day has one '1' placed randomly in the random column.

Date_Time                Date          Random
2003-12-12 1:00:54 AM    2003-12-12    1
2003-12-12 11:00:54 AM   2003-12-12    0
2003-12-12 4:02:17 PM    2003-12-12    0
2003-12-13 1:01:30 AM    2003-12-13    0
2003-12-13 11:00:24 AM   2003-12-13    0
2003-12-13 4:00:12 PM    2003-12-13    1
2003-12-14 1:00:06 AM    2003-12-14    1
2003-12-14 11:03:11 AM   2003-12-14    0
2003-12-14 4:00:32 PM    2003-12-14    0
2003-12-15 1:00:52 AM    2003-12-15    0
2003-12-15 11:01:54 AM   2003-12-15    1
2003-12-15 4:01:22 PM    2003-12-15    0
  • 1
    Could you please edit your question and post an example of your data and the expected output? – Aaron Jun 18 at 17:37
  • 1
    @Aaron I updated it with data and output – harry.p Jun 18 at 20:59
1

You can do this in a single update cursor. You'll want to use dictionaries to keep track of each date's random pick and where in the count of each date you are.

#update table
tab = r"path\to\table"
#date field
dtFld = "Date"
#random field
ranFld = "Random"


import arcpy
import random

#dictionary to store count of date
countDi = {}
#dictionary to store random value (1,2,3) per date
randomDi = {}

with arcpy.da.UpdateCursor (tab, [dtFld, ranFld]) as curs:
    for dt, ran in curs:
        #get last count from di or pick 0
        try: count = countDi [dt]
        except KeyError: count = 0
        # add one to count
        count += 1
        #get random number for date or pick one
        try: randNum = randomDi [dt]
        except KeyError: randNum = random.choice ([1, 2, 3])

        #update dictionaries
        countDi [dt] = count
        randomDi [dt] = randNum

        #check if current count is random number
        if count == randNum:
            #update row with 1
            row = (dt, 1)
        else:
            #update row with 0
            row = (dt, 0)
        #update cursor
        curs.updateRow (row)
1

Another way using collections.defaultdict(list), should work with any number of dates (not just 3 of the same):

import arcpy
from collections import defaultdict
from random import shuffle

fc = r'roadpoints'
datefield = 'date'
randfield = 'random'

#Create a Dictionary with date as key and all oids of that date as a list of values
d = defaultdict(list)
with arcpy.da.SearchCursor(fc,[datefield,'OID@']) as cursor:
    for date, oid in cursor:
        d[date.date()].append(oid)

#Create a Dictionary with oid as key and 0 or 1 as value
d2 = {}
for date, oids in d.iteritems(): #d.items() in ArcGIS Pro
    nums = [0]*(len(oids)-1)
    nums.append(1)
    shuffle(nums)
    for oid,num in zip(oids,nums):
        d2[oid] = num

#Update random column
with arcpy.da.UpdateCursor(fc,['OID@',randfield]) as cursor:
    for row in cursor:
        row[1] = d2[row[0]]
        cursor.updateRow(row)

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.