Skip to main content
Solved

Converting list values to an attribute depending on other list values

  • March 24, 2017
  • 5 replies
  • 58 views

Forum|alt.badge.img

Hi All,

In 2016.0, I have a list like this:

 

 

_list{0}.class = 1

 

_list{1}.class = 2

 

_list{2}.class = 3

 

_list{3}.class = 5

 

_list{4}.class = 2

 

_list{5}.class = 1

 

 

I need to know how many of any given class there are with the feature.

ListHistogrammer does this nicely:

 

 

_histo{0}.value = 1

 

_histo{0}.count = 2

 

_histo{1}.value = 2

 

_histo{1}.count = 2

 

_histo{2}.value = 3

 

_histo{2}.count = 1

 

_histo{3}.value = 5

 

_histo{3}.count = 1

 

 

My problem then is turning those into attributes simply. I don't want to have to explode or deconstruct my feature further (this workspace is already too large and slow).

 

 

In this example, I'd like my output feature to have attributes like these:

 

 

first_class = 2

 

other_thing = 2

 

third_item = 1

 

fourth_item = <missing>

 

final = 1

Any ideas how to do this? I could likely do it with a PythonCaller, but surely there's a better way?

Best answer by takashi

I cannot understand the naming rule for the destination attribute ('first_class', 'other_thing' ... 'final'?), but if the goal was just to map the counts to new attributes with any names corresponding to the values (1, 2, ... 5), this Python script example might help you.

# PythonCaller Script Example

def processFeature(feature):
    valueToAttr = {
        '1': 'first',
        '2': 'second',
        '3': 'third',
        '4': 'fourth',
        '5': 'fifth',
    }
    
    valueToCount = {}
    values = feature.getAttribute('_histo{}.value')
    counts = feature.getAttribute('_histo{}.count')
    if values and counts:
        for v, c in zip(values, counts):
            valueToCount[v] = c
            
        for v in valueToAttr.keys():
            if v in valueToCount:
                feature.setAttribute(valueToAttr[v], valueToCount[v])
This post is closed to further activity.
It may be an old question, an answered question, an implemented idea, or a notification-only post.
Please check post dates before relying on any information in a question or answer.
For follow-up or related questions, please post a new question or idea.
If there is a genuine update to be made, please contact us and request that the post is reopened.

5 replies

jdh
Contributor
Forum|alt.badge.img+40
  • Contributor
  • March 24, 2017

If you want to flatten the histogram as if it were a key/value pair,

 

in your histogram example you would end up with

 

1: 2

 

2: 2

 

3: 1

 

5: 1

then creating a custom transformer loop and using an attributeCreator with the new attribute as @Value(_histo{@Value(i)}.value) and the Attribute Value as @Value(_histo{@Value(i).count) should work. Where i is the loop iteration from 0 to length of list -1

 

 

If you want the attribute to be named first_class, fourth_item, etc, then python is the way to go.

Forum|alt.badge.img
  • Author
  • March 27, 2017
Upon further investigation, I'm not even sure this is possible with Python! I can't find any way to access a full list - this question from 2012 suggests the "new" API doesn't have one - https://knowledge.safe.com/questions/5463/python-and-lists.html

 

Is it possible?

 


jdh
Contributor
Forum|alt.badge.img+40
  • Contributor
  • March 27, 2017
Upon further investigation, I'm not even sure this is possible with Python! I can't find any way to access a full list - this question from 2012 suggests the "new" API doesn't have one - https://knowledge.safe.com/questions/5463/python-and-lists.html

 

Is it possible?

 

feature.getAttribute('_histogram{}.value') will return a list as will feature.getAttribute('_histogram{}.count').

 

 

If necessary you can zip them together, though I have rarely needed to do that.

 


takashi
Celebrity
  • Best Answer
  • March 27, 2017

I cannot understand the naming rule for the destination attribute ('first_class', 'other_thing' ... 'final'?), but if the goal was just to map the counts to new attributes with any names corresponding to the values (1, 2, ... 5), this Python script example might help you.

# PythonCaller Script Example

def processFeature(feature):
    valueToAttr = {
        '1': 'first',
        '2': 'second',
        '3': 'third',
        '4': 'fourth',
        '5': 'fifth',
    }
    
    valueToCount = {}
    values = feature.getAttribute('_histo{}.value')
    counts = feature.getAttribute('_histo{}.count')
    if values and counts:
        for v, c in zip(values, counts):
            valueToCount[v] = c
            
        for v in valueToAttr.keys():
            if v in valueToCount:
                feature.setAttribute(valueToAttr[v], valueToCount[v])

Forum|alt.badge.img
  • Author
  • March 27, 2017

I cannot understand the naming rule for the destination attribute ('first_class', 'other_thing' ... 'final'?), but if the goal was just to map the counts to new attributes with any names corresponding to the values (1, 2, ... 5), this Python script example might help you.

# PythonCaller Script Example

def processFeature(feature):
    valueToAttr = {
        '1': 'first',
        '2': 'second',
        '3': 'third',
        '4': 'fourth',
        '5': 'fifth',
    }
    
    valueToCount = {}
    values = feature.getAttribute('_histo{}.value')
    counts = feature.getAttribute('_histo{}.count')
    if values and counts:
        for v, c in zip(values, counts):
            valueToCount[v] = c
            
        for v in valueToAttr.keys():
            if v in valueToCount:
                feature.setAttribute(valueToAttr[v], valueToCount[v])
Thanks, that did the trick nicely, I couldn't find anything how to access lists with Python, hence my problem. Relating to the naming convention, I was trying to express that the attribute names would be arbitrary, but that's easily resolved in your version by changing the dict values.