How do you sort a dataset?

I find myself stumped again! I have sorted lists before but I am at a loss as to why I cannot do this. The table I am trying to sort has three columns and about 50 rows.

ds = event.source.parent.getComponent('Table').data pyData = system.dataset.toPyDataSet(ds) ds.sort()

This is the error …

[quote]Traceback (innermost last):
File “event:actionPerformed”, line 3, in ?
AttributeError: sort

at org.python.core.Py.AttributeError(Py.java)
at org.python.core.PyInstance.invoke(PyInstance.java)
at org.python.pycode._pyx150.f$0(<event:actionPerformed>:3)
at org.python.pycode._pyx150.call_function(<event:actionPerformed>)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyCode.call(PyCode.java)
at org.python.core.Py.runCode(Py.java)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:395)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:139)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:247)
at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:55)
at $Proxy6.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Ignition v7.3.1 (b496)
Java: Sun Microsystems Inc. 1.6.0_27
[/quote]

What is the proper way to perform a sort?
Thanks,

Yeah, DataSet doesn’t have a sort() method… looks like you need to sort it yourself. Will get back to you with a code snippet…

Correction to the original post. (I had tried every combination I could think of)

ds = event.source.parent.getComponent('Table').data pyData = system.dataset.toPyDataSet(ds) pyData.sort()

This is a bit ugly… we should really add a scripting function that will sort a DataSet.

headers = ["Column 1", "Column 2"]
data = [['z','foo'],['w','bar'],['a','baz']]
ds = system.dataset.toDataSet(headers, data)

def sortDataSet(ds, key_column = 0):
	# create headers
	headers = [ds.getColumnName(x) for x in range(ds.columnCount-1)]
	
	# create data
	import system
	py_ds = system.dataset.toPyDataSet(ds)
	rows = [py_ds[x] for x in range(len(py_ds))]
	rows.sort(lambda x,y,key=key_column: cmp(x[key], y[key]))
	data = [[row[x] for x in range(len(rows)-1)] for row in rows]
	
	return system.dataset.toDataSet(headers, data)

print sortDataSet(ds)

I copied your code and it worked in the playground but not when I entered it into my project.

def sortData(ds, key_column = 2): import system headers = [ds.getColumnName(x) for x in range(ds.columnCount)] pyData = system.dataset.toPyDataSet(ds) rows = [pyData[x] for x in range(len(pyData))] rows.sort(lambda x,y,key=key_column: cmp(x[key], y[key])) data = [[row[x] for x in range(len(rows)-1)] for row in rows] return system.dataset.toDataSet(headers, data)

Line 366 is the 'data = ’ statement above.

[quote]Traceback (innermost last):
File “event:actionPerformed”, line 37, in ?
File “module:math”, line 366, in sortData
IndexError: Column index 3 out of range.

at org.python.core.Py.IndexError(Py.java)
at com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities$PyDataSet$PyRow.__getitem__(DatasetUtilities.java:102)
at sun.reflect.GeneratedMethodAccessor97.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java)
at org.python.core.PyMethod.__call__(PyMethod.java)
at org.python.core.PyObject.__call__(PyObject.java)
at org.python.core.PyInstance.invoke(PyInstance.java)
at org.python.core.PyInstance.__getitem__(PyInstance.java)
at org.python.pycode._pyx273.sortData$16(<module:math>:366)
at org.python.pycode._pyx273.call_function(<module:math>)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyFunction.__call__(PyFunction.java)
at org.python.core.PyObject.invoke(PyObject.java)
at org.python.pycode._pyx272.f$0(<event:actionPerformed>:37)
at org.python.pycode._pyx272.call_function(<event:actionPerformed>)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyCode.call(PyCode.java)
at org.python.core.Py.runCode(Py.java)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:395)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:139)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:247)
at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:55)
at $Proxy5.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Ignition v7.3.1 (b496)
Java: Sun Microsystems Inc. 1.6.0_27
[/quote]

I attached the data I am working with. I am trying to sort this so I can extract rows for the top 5 heights.
Thanks,
data.txt (2.76 KB)

I think there’s a problem in the script, which you seemed to catch in one place already, where the row count is being used instead of the column count.

I didn’t mock this up, but it looks like on that line you want to loop through all columns for all rows. Instead of “data = [[row[x] for x in range(len(rows)-1)] for row in rows]” I think you want:

data = [[row[x] for x in range(ds.columnCount)] for row in rows]

EDIT:
Here is the final CORRECT version of this code.

[code]headers = [“Column 1”, “Column 2”]
data = [[‘z’,‘foo’],[‘w’,‘bar’],[‘a’,‘baz’]]
ds = system.dataset.toDataSet(headers, data)

def sortDataSet(ds, key_column = 0):

create headers

headers = [ds.getColumnName(x) for x in range(ds.columnCount)]

create data

import system
py_ds = system.dataset.toPyDataSet(ds)
rows = [py_ds[x] for x in range(len(py_ds))]
rows.sort(lambda x,y,key=key_column: cmp(x[key], y[key]))
data = [[row[x] for x in range(ds.columnCount)] for row in rows]

return system.dataset.toDataSet(headers, data)

this uses the Ignition dataset (not a pydataset) that was created in line 3

print sortDataSet(ds)[/code]

Regards,

Scripting and expression functions for sorting a dataset have been added for the 7.4 final release.

in 8.1 the sort method does not sort my dataset

Are you from the future? There is no version 8.1 :slight_smile:

Show us the code you’re using?