The Usage property for an item returns None or Empty Dataframe

882
3
Jump to solution
12-16-2022 06:20 AM
JoelRogers
New Contributor II

The syntax for returning the usage of an item in ArcGIS online for 30 days and 60 days returns None or Empty Dataframe when the as_df paramater is True. I am using version 2.0.1 of the API and have tried it in desktop Jupyter notebook, ArcGIS Online Jupyter notebook, and standalone script.

my_content = gis.content.search(query="owner:" + gis.users.me.username, max_items=15)

for item in my_content:
    df_usage30 = item.usage(date_range='30D', as_df=True)
    df_usage60 = item.usage(date_range='60D', as_df=True)
    print(df_usage30, " ",df_usage60)

 

This is for all kinds of items and ones that have been created recently and I know are being used. You can see the usage statistics in the Usage panel of the item description in AGOL. When I use the item.numViews property on the same items, it returns the correct views (I know views and usage are different).

All I can find are posts about how this is an issue, bugs that don't seem to be resolved, and Github issues that claim they are resolved. Any guidance about what I should be doing differently are welcome..

Here is one of the things I have found regarding this subject:

item.usage() returns None when using the default output (as_df=True). Version 2.0.0 · Issue #1205 · ...

 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
JoelRogers
New Contributor II

After speaking with Esri support I have learned that this is currently a bug (BUG-000154587). There is currently no way to get a dataframe returned when using the date ranges of "30D" and "60D". It currently only returns an empty dataframe or None. I did discover, however, that the dictionary response option still works.

To get a dictionary for the items usage you have to set the as_df parameter to False. Once the dictionary is returned you have to parse out the parts you need and sum the usage for each day to get the total usage for that time period. I am not very good at dealing with dictionaries but breaking the dictionary down to its component parts like this solves my issue.

Assume you have a dictionary returned for an item like this:

testDictionary = item.usage(date_range='30D',as_df=False)

result:

{'startTime': 1669593600000, 'endTime': 1672272000000, 'period': '1d', 'data': [{'etype': 'randomUser', 'name': 'randomFeatureService', 'stype': 'features', 'num': [['1669593600000', '0'], ['1669680000000', '0'], ['1669766400000', '0'], ['1669852800000', '0'], ['1669939200000', '0'], ['1670025600000', '0'], ['1670112000000', '0'], ['1670198400000', '0'], ['1670284800000', '0'], ['1670371200000', '0'], ['1670457600000', '0'], ['1670544000000', '0'], ['1670630400000', '0'], ['1670716800000', '0'], ['1670803200000', '0'], ['1670889600000', '0'], ['1670976000000', '0'], ['1671062400000', '0'], ['1671148800000', '0'], ['1671235200000', '0'], ['1671321600000', '0'], ['1671408000000', '0'], ['1671494400000', '0'], ['1671580800000', '0'], ['1671667200000', '0'], ['1671753600000', '0'], ['1671840000000', '0'], ['1671926400000', '0'], ['1672012800000', '0'], ['1672099200000', '27'], ['1672185600000', '79']]}]}

You can break each part down and then sum the totals per day like this:

dataFromDict = testDictionary['data']
nestedDict = dataFromDict[0]
numFromNested = nestedDict['num']

totalUsage30 = 0

for list in numFromNested:
    totalUsage30 += int(list[1])

print(totalUsage30)

The "num" keyword in the nested dictionary holds all of the information for day (epoch time) and usage per day in nested lists. This gets me the 30-day usage. I have to repeat the process for the 60-day usage.

I also asked whether the item.numViews property could be filtered to specific timeframes and that is not possible. It would be more beneficial to me in my specific scenario to see views instead of usage for 30 and 60 days, but that is not currently an option.

View solution in original post

0 Kudos
3 Replies
JoelRogers
New Contributor II

After speaking with Esri support I have learned that this is currently a bug (BUG-000154587). There is currently no way to get a dataframe returned when using the date ranges of "30D" and "60D". It currently only returns an empty dataframe or None. I did discover, however, that the dictionary response option still works.

To get a dictionary for the items usage you have to set the as_df parameter to False. Once the dictionary is returned you have to parse out the parts you need and sum the usage for each day to get the total usage for that time period. I am not very good at dealing with dictionaries but breaking the dictionary down to its component parts like this solves my issue.

Assume you have a dictionary returned for an item like this:

testDictionary = item.usage(date_range='30D',as_df=False)

result:

{'startTime': 1669593600000, 'endTime': 1672272000000, 'period': '1d', 'data': [{'etype': 'randomUser', 'name': 'randomFeatureService', 'stype': 'features', 'num': [['1669593600000', '0'], ['1669680000000', '0'], ['1669766400000', '0'], ['1669852800000', '0'], ['1669939200000', '0'], ['1670025600000', '0'], ['1670112000000', '0'], ['1670198400000', '0'], ['1670284800000', '0'], ['1670371200000', '0'], ['1670457600000', '0'], ['1670544000000', '0'], ['1670630400000', '0'], ['1670716800000', '0'], ['1670803200000', '0'], ['1670889600000', '0'], ['1670976000000', '0'], ['1671062400000', '0'], ['1671148800000', '0'], ['1671235200000', '0'], ['1671321600000', '0'], ['1671408000000', '0'], ['1671494400000', '0'], ['1671580800000', '0'], ['1671667200000', '0'], ['1671753600000', '0'], ['1671840000000', '0'], ['1671926400000', '0'], ['1672012800000', '0'], ['1672099200000', '27'], ['1672185600000', '79']]}]}

You can break each part down and then sum the totals per day like this:

dataFromDict = testDictionary['data']
nestedDict = dataFromDict[0]
numFromNested = nestedDict['num']

totalUsage30 = 0

for list in numFromNested:
    totalUsage30 += int(list[1])

print(totalUsage30)

The "num" keyword in the nested dictionary holds all of the information for day (epoch time) and usage per day in nested lists. This gets me the 30-day usage. I have to repeat the process for the 60-day usage.

I also asked whether the item.numViews property could be filtered to specific timeframes and that is not possible. It would be more beneficial to me in my specific scenario to see views instead of usage for 30 and 60 days, but that is not currently an option.

0 Kudos
Ian-Horn
New Contributor II

I posted the same issue last night and was pointed to the your post.  Mine is https://community.esri.com/t5/python-questions/item-usage-not-correctly-getting-requests/m-p/1272901...

What I'm thinking about doing, because I'm already creating some dates as variables because I want to get the previous month's request, is to just run the '6M' and then filter out the dates I don't want with conditionals.

Something like:

with gis.content.get(ITEM_ID) as my_item:
my_result = my_item.usage(date_range = '6M', as_default = True)
 
if my_result < custom_date1:
skip
elif my_result > custom_dat2:
skip
else:
print(f'This item received {my_result:, d} requests last month.')

 

Hopefully my logic isn't flawed.  I sure wish they'd fix this bug.

0 Kudos
Ian-Horn
New Contributor II

*as_df = True

0 Kudos