# Speed problem in the execution of an action in perspective

**URL:** <https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [June 21, 2023, 11:11pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369 "2023-06-21T23:11:59Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cristian\_Gomez](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cristian_gomez/32/49040_2.png) [@Cristian\_Gomez](https://forum.inductiveautomation.com/u/Cristian_Gomez)\
**Post date:** [June 21, 2023, 11:11pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/1 "2023-06-21T23:11:59Z")

</div>

Hello, good afternoon  
I have a speed problem in the execution of an action in perspective. The version of the company is 8.1.20 so it does not include the filtering property in the tables, therefore I used dop-down boxes for this purpose, but the execution of the command is taking more than 30 seconds, any idea to optimize please.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/f/e/fe7604503ca7b2f394564dae4d323f8e0a95b4d0.png)  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/0/b065043628d0b863a42d40e0b0655fb49f266a25.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 21, 2023, 11:25pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/2 "2023-06-21T23:25:57Z")

</div>

It'd be nice if you posted your code as text, instead of images, if you want folks to take a look at it and optimize it.

From experience, it's probably going to be significantly faster to construct a list of row indices to delete/keep and 'trim' the input dataset using `system.dataset.deleteRows` as one operation rather than continually resizing a PyDataset/list of rows. You could also be doing some extra work to 'short circuit' your conditions - as it's written now, you might be checking a row for a foreman/pumper match even if the district match failed, for instance.

---

<div class="post-metadata">

**Author:** ![Cristian\_Gomez](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cristian_gomez/32/49040_2.png) [@Cristian\_Gomez](https://forum.inductiveautomation.com/u/Cristian_Gomez)\
**Post date:** [June 21, 2023, 11:32pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/3 "2023-06-21T23:32:31Z")

</div>

Thank you very much, I will work on the basis of what you say.  
I will put the initial code here as well.

```auto
def transform(self, value, quality, timestamp):
	selectedDistrict=self.getSibling("Dropdown").custom.SelectedValue
	selectedForemen=self.getSibling("Dropdown_1").custom.SelectedValue
	selectedPumper=self.getSibling("Dropdown_0").custom.SelectedValue
	HeaderList=["Meter","Graph","Type","Time","Meter ID","Status","County","Well ID","Distric","Foreman","Pumper","Valve Control","PID Control","Gas Rate","Gas Today", "Gas Yest","Net Gas","Avg 7","Best 7","Vol Ex Diff","Vol Ex Pct","DP","CPress","CAvg","CDraw","TPress","TAvg","TDraw","SP","Temp","FTT","FTY","RT Order","Demand Poll","Demand Poll Status","Battery","Poll Status","Type_Full","Sales Gas"]
	data = system.dataset.toPyDataSet(value)
	ListFilt = []
	if selectedDistrict != "<All District>" or selectedForemen != "<All Foremen>" or selectedPumper != "<All Pumpers>":
		for row in data:
			DistrictMatch = selectedDistrict == "<All District>" or row ["District"] == selectedDistrict
			ForemenMatch = selectedForemen == "<All Foremen>" or row ["Foreman"] == selectedForemen
			PumperMatch = selectedPumper == "<All Pumpers>" or row ["Pumper"] == selectedPumper
			if DistrictMatch and ForemenMatch and PumperMatch:
				ListFilt.append(row)
		filtered_dataset = system.dataset.toDataSet(HeaderList, ListFilt)
		return filtered_dataset	
	return value

```

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [June 22, 2023, 12:56am UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/4 "2023-06-22T00:56:44Z")

</div>

I would expect this to execute quicker.

```auto
def transform(self, value, quality, timestamp):
	selectedDistrict=self.getSibling("Dropdown").custom.SelectedValue
	selectedForemen=self.getSibling("Dropdown_1").custom.SelectedValue
	selectedPumper=self.getSibling("Dropdown_0").custom.SelectedValue
	data = system.dataset.toPyDataSet(value)
	if any(selectedDistrict != "<All District>",selectedForemen != "<All Foremen>",selectedPumper != "<All Pumpers>"):
		ListFilt = []
		for index,row in enumerate(data):
			DistrictMatch = selectedDistrict in {"<All District>",row ["District"]}
			ForemenMatch = selectedForemen in {"<All Foremen>",row ["Foreman"]}
			PumperMatch = selectedPumper in {"<All Pumpers>",row ["Pumper"]}
			if all(DistrictMatch,ForemenMatch,PumperMatch):
				ListFilt.append(index)
		return system.dataset.deleteRows(data, ListFilt)
	return value

```

---

<div class="post-metadata">

**Author:** ![Cristian\_Gomez](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cristian_gomez/32/49040_2.png) [@Cristian\_Gomez](https://forum.inductiveautomation.com/u/Cristian_Gomez)\
**Post date:** [June 22, 2023, 1:57pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/5 "2023-06-22T13:57:15Z")

</div>

Thank you very much, the code as such performs the reverse process, since it eliminates the rows where the statements are true, but it gives me the idea to re-structure it.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 22, 2023, 2:45pm UTC](https://forum.inductiveautomation.com/t/speed-problem-in-the-execution-of-an-action-in-perspective/75369/6 "2023-06-22T14:45:22Z")

</div>

You might find my new `where()` expression function helpful:

> [@Automation Professionals' Integration Toolkit Module](https://forum.inductiveautomation.com/t/automation-professionals-simulation-aids-v2/74934/5):
>
> I have spent my holiday poking at this. Wanted to provide an efficient replacement for a common use of python transforms: Make a (Perspective) table that dynamically populates both .data and .columns from source dataset that isn't constrained to any particular structure or data types. In Vision, one can achieve this (mostly) by pre-populating the column attributes dataset with all of the possible column names your application might deliver. No such thing in Perspective. But a transform can …

In this case, your transform would look something like this:

```auto
where({value},
    ({path.to.District.Dropdown.custom.SelectedValue} != '<All District>' && {path.to.District.Dropdown.custom.SelectedValue} != it()['District']) ||
    ({path.to.Foreman.Dropdown.custom.SelectedValue} != '<All Foremen>' && {path.to.Foreman.Dropdown.custom.SelectedValue} != it()['Foreman']) ||
    ({path.to.Pumper.Dropdown.custom.SelectedValue} != '<All Pumpers>' && {path.to.Pumper.Dropdown.custom.SelectedValue} != it()['Pumper'])
)

```

I suspect this will run much faster than any script transform.
