turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- JMP User Community
- :
- Discussions
- :
- perform calculation evaluation in associative arra...

Topic Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 26, 2017 3:00 PM
(1723 views)

Hello,

I am trying to get a function to return a standard deviation calculation stored inside an associative array, my code will only return the expression of the associative array and not the calculation. would you please tell me what is wrong with my code.

cvf= Max**(**replist**)**;// my cvf in the file is 8

cv=Associative Array**()**;

cv**[****6]**=Associative Array**({(**Std Dev**(5**,**6**,**7**,**8**,**9**,**10))})**;

cv**[****8]**=Associative Array **({(**Std Dev**(5**,**6**,**7**,**8**,**9**,**10**,**11**,**12))})**;

cv**[****12]**=Associative Array **({(**Std Dev**(5**,**6**,**7**,**8**,**9**,**10**,**11**,**12**,**13**,**14**,**15**,**16))})**;

CVC = Function**(****{**ref**}**,Local **({**cv = Associative Array**({**cvf, Eval**(**cvf**)}** **)}**,cv << **get values(**cvf**))**;cv**[**ref**])**;**)**;

a=CVC**(**cvf**)**;

eval**(**eval expr**(**a**))**;

Show(a);

this is the output that I get:

a = Associative Array({{Std Dev( 5, 6, 7, 8, 9, 10, 11, 12 ), 1}}, 0);

this is the output that I want: a= 2.5

2 ACCEPTED SOLUTIONS

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 29, 2017 3:50 PM
(3103 views)

Solution

Hi Mark ,

I use your example and I am able to get the row number correctly, but the average and standard deviation is not correct. And my table is over 10,000 line, the calculation is bit slow. Would you please tell me where do I did wrong? thanks.

Names Default to Here**(** **1** **)**;

dt = Open**(** "$SAMPLE_DATA/Big Class.jmp" **)**;

Summarize**(** age grp = By**(** :age**)**,sex grp= By **(**:sex**)**, avg = Mean**(** :height **)**, sd = Std Dev**(** :height **)** **)**;

age grp = Associative Array**(** :age **)** << **Get Keys**;

sex grp = Associative Array**(** :sex **)** << **Get Keys**;

dt << **New Column(** "CV" **)**;

For**(** g = **1**, g <= nitems**(**age grp**)**, g++,

for **(**i =**1**, i<=nitems**(**sex grp**)**, i++,

rows = dt <<**get rows where****(**:age == age grp**[**g**]** & :sex == sex grp**[**i**])**;

:CV**[**rows**]** = **100** * sd**[**i**]** / avg**[**i**]**;

**))**;

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 30, 2017 2:47 AM
(3089 views)

Solution

You could try to see if this is more effcient (which I might expect):

```
Names Default To Here( 1 );
// Example table
dt = Open("$SAMPLE_DATA/Big Class.jmp");
// Edit to taste . . .
var = Column(dt, "height");
byVars = {Column(dt, "sex"), Column(dt, "age")};
// Use a summary table with formula column
dt2 = dt << Summary(Group(byVars), Mean(var), Std Dev(var));
Column(dt2, 4) << setName("Mean");
Column(dt2, 5) << setName("StdDev");
dt2 << New Column( "CV", Numeric, "Continuous", Format( "Percent", 12, 3 ), Formula(:StdDev/:Mean));
```

If you need the CV values in the original table, use 'Tables > Join'.

10 REPLIES

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 26, 2017 3:42 PM
(1718 views)

I figure out my problem, but I have a new problem.

my associateive array is a formula, and I need to retrive the key to perform the calculation.

my code will return a, which is the formula on how to calculate standard deviation. but when I put the formula into a new formula, the new formula doesn't perform the calcualtion.

a=CVC**(**cvf**)**<<**get keys****(**cvf**)**;

show**(**a**)**;// this is the formula with a:

{Std Dev(:INSTRUMENT_SIGNAL[Row() + 8], :INSTRUMENT_SIGNAL[Row() + 1], :INSTRUMENT_SIGNAL[Row() + 2], :INSTRUMENT_SIGNAL[Row() + 3], :INSTRUMENT_SIGNAL[Row() + 4], :INSTRUMENT_SIGNAL[Row() + 5], :INSTRUMENT_SIGNAL[Row() + 6], :INSTRUMENT_SIGNAL[Row() + 7])};

but once I put a into the new formula below: a would do the calculation. Please help!

col2<<**set formula****(**If**(** :RUNSAMPLEKIND == "TITERC.NEG",**(**a/ :Average Signal**)** * **100****)**,

If**(** :RUNSAMPLEKIND**[**Row**()]** == :RUNSAMPLEKIND**[**Row**()** + **1]**,

If**(** :REP**[**Row**()]** != **2**,**(**Std Dev**(** :INSTRUMENT_SIGNAL**[**Row**()** + **1]**, :INSTRUMENT_SIGNAL**[**Row**()]** **)** /:Average Signal**)** * **100****)****)****)**;

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 27, 2017 5:08 AM
(1698 views)

Let's start over.

- What are you trying to do?
- What is your data like?
- How is it organized?
- What are the results you need?
- What do you want to do with the results?

It isn't clear to me that you need to use an associative array.

Learn it once, use it forever!

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 27, 2017 9:33 AM
(1688 views)

there are three columns in a data table, and one will indicate replicate number, and the other will have a signal output for the replicate, and the last one will have the dataID. and I need to calculate the standard deviation for all dataID. all of the data will only have two replicate, except one specific type named "Titer" and depending on the where the data is generated, data type "Titer" can have 6, 8 or 12 replicate. hence, i make those three cases as an array and link them to the replicate column.

my code and return the formula to standard devaition calculation, however, when I put those in a new columns for CV calcualtion, it doesn't do anything.

the other option that I can think is using the Tabulate platform to get the standard devation and put them in an array and assign them back to the new column. Any suggestion?

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 27, 2017 9:51 AM
(1685 views)

Try this example:

```
Names Default to Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
Summarize( age grp = By( :age ), avg = Mean( :height ), sd = Std Dev( :height ) );
age grp = Associative Array( :age ) << Get Keys;
dt << New Column( "CV" );
For( g = 1, g <= N Items( age grp ), g++,
rows = dt << Get Rows Where( :age == age grp[g] )
:CV[rows] = 100 * sd[g] / avg[g];
);
```

Learn it once, use it forever!

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 29, 2017 1:26 PM
(1597 views)

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 29, 2017 3:50 PM
(3104 views)

Hi Mark ,

I use your example and I am able to get the row number correctly, but the average and standard deviation is not correct. And my table is over 10,000 line, the calculation is bit slow. Would you please tell me where do I did wrong? thanks.

Names Default to Here**(** **1** **)**;

dt = Open**(** "$SAMPLE_DATA/Big Class.jmp" **)**;

Summarize**(** age grp = By**(** :age**)**,sex grp= By **(**:sex**)**, avg = Mean**(** :height **)**, sd = Std Dev**(** :height **)** **)**;

age grp = Associative Array**(** :age **)** << **Get Keys**;

sex grp = Associative Array**(** :sex **)** << **Get Keys**;

dt << **New Column(** "CV" **)**;

For**(** g = **1**, g <= nitems**(**age grp**)**, g++,

for **(**i =**1**, i<=nitems**(**sex grp**)**, i++,

rows = dt <<**get rows where****(**:age == age grp**[**g**]** & :sex == sex grp**[**i**])**;

:CV**[**rows**]** = **100** * sd**[**i**]** / avg**[**i**]**;

**))**;

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 30, 2017 2:47 AM
(3090 views)

You could try to see if this is more effcient (which I might expect):

```
Names Default To Here( 1 );
// Example table
dt = Open("$SAMPLE_DATA/Big Class.jmp");
// Edit to taste . . .
var = Column(dt, "height");
byVars = {Column(dt, "sex"), Column(dt, "age")};
// Use a summary table with formula column
dt2 = dt << Summary(Group(byVars), Mean(var), Std Dev(var));
Column(dt2, 4) << setName("Mean");
Column(dt2, 5) << setName("StdDev");
dt2 << New Column( "CV", Numeric, "Continuous", Format( "Percent", 12, 3 ), Formula(:StdDev/:Mean));
```

If you need the CV values in the original table, use 'Tables > Join'.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jul 3, 2017 2:38 AM
(1542 views)

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Get Direct Link
- Email to a Friend
- Report Inappropriate Content

Jun 30, 2017 4:32 AM
(1569 views)

I apologize for missing the fact that you have two grouping variables. This modified script will show you how it works.

```
Names Default to Here( 1 );
// Open example of a data table
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
// Estimate group statistics and group identities
Summarize( age sex grp = By( :age, :sex ), avg = Mean( :height ), sd = Std Dev( :height ) );
// Make a new columns for group result
dt << New Column( "Avg" ) << New Column( "SD" ) << New Column( "CV" );
// Iterate over groups
For( g = 1, g <= N Items( age grp ), g++,
// Convert :age level to match data type of identity
rows = dt << Get Rows Where( Char( :age ) == age sex grp[1][g] & :sex == age sex grp[2][g] );
:Avg[rows] = avg[g];
:SD[rows] =sd[g];
:CV[rows] = 100 * sd[g] / avg[g];
);
```

I don't think that an associative array is the most efficient way to identify the groups. The Summarize() function simultaneously estimates the group statistics and identifies the associated group using two parallel lists of group levels. The only downside, in my opinion, is that the grouping levels are always character strings even if the original levels are numeric, such as :age levels in this case. So I had to convert the :age level for the comparison used in getting the target row numbers.

Now you have two approaches, including Ian's solution using Summary command\.

Learn it once, use it forever!