Message Boards Message Boards

0
|
4618 Views
|
22 Replies
|
5 Total Likes
View groups...
Share
Share this post:

Using Dynamic as a pattern to retrieve a Position from a list?

Posted 2 years ago

I have a manually entered table of model numbers and their associated parameters. I want to be able to select a model number using a PopupMenu and then retrieve the parameters associated with that model number for further processing. If I use one of the model numbers directly, it returns the position correctly, but if I use the Dynamic that returns that same model number I just get empty curly brackets?

POSTED BY: Kevin Ulmer
22 Replies
Posted 2 years ago

Okay, three things before we get started. First, I suggest you first tackle the problems of creating a polynomial equation expression for given indeterminates and coefficients before worrying about the dynamic aspect.

Second, I strongly recommend that you do not literally use Set to define your indexed coefficient variables. Since you're wanting to use Dynamic, I'm anticipating that you'll be wanting to update those coefficient variables, but once you use Set the first time, any subsequent Set will fail because it'll try to assign a value to a number (instead of a variable). So, we can use Rules or we can try to use Dynamic in yet another way.

Third, you mention solving equations, and I'm worried that injecting Dynamic into your solution process will get messy and maybe even intractable. But, since I don't know what your solve process consists of, I don't have suggestions.

POSTED BY: Eric Rimbey
Posted 2 years ago

Oops, I should have made my examples more like your polynomial. Instead of

MyPolynomial[Array[Indexed[a,#]&,5],Array[Indexed[x,#]&,5]]

you'll probably do something more like this:

MyPolynomial[Array[Indexed[a, #] &, 5], Array[Indexed[x, #]^# &, 5]]
POSTED BY: Eric Rimbey
Posted 2 years ago

The real table is significantly larger and each row (Model #) contains a number of parameters and the coefficients for a series of polynomial equations specific to that Model that I will need to solve of the form:

y^2 = Subscript[a, 1]x + Subscript[a, 2] x^2 +
Subscript[a, 3] x^3 + Subscript[a, 4] x^4 +
Subscript[a, 5] x^5 + Subscript[a, 6] x^6 

where the coefficients a1, a2...a6 are the elements of the row for that Model. So in this simplified example I want to be able to interactively select a Model Number, e.g., 4146 and then assign the corresponding row elements as follows: a1 = 0.2, a2 = 0.7, a3 = 0.21 and a4 =0.63. Hope that helps clarify?

POSTED BY: Kevin Ulmer
Posted 2 years ago

Thanks again, Eric. In your very first reply you had used:

keyedData = Association[First@# -> Rest@# & /@ data] 

but when you started explaining this in more detail following BOOKMARK you started with an "inverted" and simplified form:

keyedData = (Rest@# -> First@#) & /@ data

The further details, however, all showed the model numbers as keys and you ended that reply with "...so we finally arrive at (First@# -> Rest@#) & /@ data." I was confused as to which to use. I did goof with the PopupMenu when I left out the keyedData. The new version attached now works as you indicated and produces the appropriate list of values as output, but now I can't figure out how to get each of those values assigned to the individual coefficients? I hope this will be the last time I will pester you and greatly appreciate all your patience.

Attachments:
POSTED BY: Kevin Ulmer
Posted 2 years ago

I'm sorry, but I don't understand your question. Can you post the desired output?

POSTED BY: Eric Rimbey
Posted 2 years ago

Okay, I re-opened one of your earlier notebooks, and I see a bunch of coef1= assignments, so that must be what you're referring to. But I still don't understand what you're actually after. Each of those assignments overrides the previous one. And I suspect that there is some subsequent step that you're going to want to take once you have your coefficients. So, if you can just jump to the "punchline" and tell me where this is going, there may be a much better way to get there. Like, maybe the coefficients need to be the dynamic bit. Or maybe we can just create a static structure and index into it with helper functions. Or maybe there is a different question here altogether that deserves a separate post. As I see it, we've "solved" your original question about how to dynamically extract the pararmaters from a row of data.

POSTED BY: Eric Rimbey
Posted 2 years ago

In your notebook, you have this:

keyedData = (First@# -> Rest@#) & /@ data

I suggested (find my BOOKMARK) this:

keyedData = (Rest@# -> First@#) & /@ data

This difference is necessary because it allows us to take advantage of some nice behavior in PopupMenu.

In your notebook you have this:

PopupMenu[Dynamic[model], modelNumbers]

That doesn't use the keyedData at all, which was the whole point of creating keyedData. I suggested this:

PopupMenu[Dynamic[model], keyedData, data[[1, 1]]]

Looking at it now, I'd probably rename "model" to something more descriptive, but whatever.

Once you've made these changes (and evaluated them), you can use this:

Dynamic[model]

to see the value of the paramters for the key selected by your PopupMenu.

POSTED BY: Eric Rimbey
Posted 2 years ago

Eric - I believe I have followed your instructions but still end up with the same problem of the correct dynamic position being enclosed in {{ }}, and I cannot extract just the enclosed number to use further. I have added comments to the attached program that I think explains what I have done at each step following your instructions. I'm sorry to bother you once more but I keep getting stuck here. Would you be kind enough to insert the magic steps at the end to make this finally work? Many thanks again!

Attachments:
POSTED BY: Kevin Ulmer
Posted 2 years ago

How do I ... get the values of the coefficients I need for further calculation from the model I have selected

I answered this above. I went back and added BOOKMARK to the post that answers this. Just do a text search of "bookmark" on this page to find it.

How do I "extract" that number between the curly brackets to use as a rowIndex...

Well, it's funny you used the work "extract". Mathematica has a function Extract that works in conjunction with Position. You don't need this, however, if you just go find my previous answer. But for future use, you should definitely go read the documentation on Extract.

I don't see any difference between modelPosition = Dynamic[Position[modelNumbers, model]] and Dynamic[modelPosition = Position[modelNumbers, model]] using FullForm

Okay, because of the order in which you're doing things in your notebook, it might not be obvious. But here's a simple notebook to illustrate the difference between the two ways of doing it. I don't know how this is going to end up displaying on this webpage--you should experiment withing Mathematica itself.

POSTED BY: Eric Rimbey
Posted 2 years ago

Hi Eric -

I'm still struggling with this. Your last suggestion for obtaining a Dynamic modelPosition yields the correct number, but it is inside two sets of curly brackets {{ }}, which "cannot be used as a part specification". Also, I don't see any difference between modelPosition = Dynamic[Position[modelNumbers, model]] and Dynamic[modelPosition = Position[modelNumbers, model]] using FullForm as you suggest? How do I "extract" that number between the curly brackets to use as a rowIndex so I can get the values of the coefficients I need for further calculation from the model I have selected as in the example where I have explicitly entered row 3? This seems like it should be so simple. Thanks again!

Attachments:
POSTED BY: Kevin Ulmer
Posted 2 years ago

"...It displays the current value of model, but it doesn't "simplify" to just model...." explains it sufficiently for me. Thanks once again for all the hand holding on this!

POSTED BY: Kevin Ulmer
Posted 2 years ago

Thank you for walking me through all of that, Eric, still so much to learn and absorb. The actual table I am using is a bit larger and was copied from a paper. I used the menu Insert -> Table/Matrix -> New... to create the empty table of the proper size and then manually entered the data from the paper. I do now appreciate and understand the utility of using an Association, but from the documentation I thought I would need to re-enter all of the data again to create that. Now I see how it can simply be done after the fact and quite "simply". The bit I still do not understand is why, if I use Dynamic[model] as the pattern to search for in Position the output is { }, but if I use that actual current value of Dynamic[model], e.g., 4147 I get the output {{4}}. Why the difference? It's not critical given your elegant solution, but I'm curious to understand.

Attachments:
POSTED BY: Kevin Ulmer
Posted 2 years ago

Hmm. I think you must be referring to code that you haven't posted here. The code you posted has no usage of Position. You might be getting {} for Position because when you run your code fresh there is no value assigned to model yet. But that's just speculation. I'd need to see the code your talking about.

POSTED BY: Eric Rimbey
Posted 2 years ago

Oh, sorry, I didn't see the attachment. Let me look.

POSTED BY: Eric Rimbey
Posted 2 years ago

Okay, I think you're referring to this:

modelPosition = Position[modelNumbers, Dynamic[model]]

I don't think that I yet fully grok how Dynamic works in every situation, but here's what I think is happening. The subexpression that Position is searching for is Dynamic[model]. Now, Dynamic[model] is it's own expression, it doesn't evaluate to the value of model. It displays the current value of model, but it doesn't "simplify" to just model.

Position[{a, b, c}, Dynamic[a]] (*gives {}*)
Position[{Dynamic[a], b, c}, Dynamic[a]] (*gives {{1}}*)

You get the above results regardless of whether a has been assigned a value yet.

Here are two alternatives:

modelPosition = Dynamic[Position[modelNumbers, model]]
(*This sets up modelPosition to be a Dynamic expression.*)

Dynamic[modelPosition = Position[modelNumbers, model]]
(*This sets up a Dynamic expression, and the update that happens
is that the variable modelPosition gets reset depending on the new value of model.*)

Visually, you won't be able to distinguish the two, but if you evaluate one and then look at FullForm[modelPosition] and then evaluate the other and look at FullForm[modelPosition] again, you can see the difference.

POSTED BY: Eric Rimbey
Posted 2 years ago

As for your other questions:

I also still do not understand how the data is structured without invoking that Association and why Dynamic[model] does not match the entries for the model numbers in the table

I'm actually not sure what you're asking. Dynamic can be confusing. It basically sets up a particular part of an output to be automatially updated. The output of Dynamic[model] will just look like whatever the current value of model is, but it'll be a special thing such that if model's value changes, that part of your notebook will automatically change to reflect the new value. But to your question, Dynamic[model] does match the entries in your table. Or at least it seems that way to me, so I must be misunderstanding your question.

As for not understanding "how the data is structured", I again must be just not understanding what you're getting at. Do you mean "how" as in "the process for creating the data"? If so, well, that's what the code I wrote does, so you'll need to try to understand that code. Or do you mean "how the data is structured" as in "what is the structure of the data"? You can just look at it and inspect it. This seems obvious, so I guess I just don't know what you're asking.

POSTED BY: Eric Rimbey
Posted 2 years ago

Sorry for the cryptic notation. I can walk you through it a bit. First, I looked at your data, which is just a list of lists. You indicated that there is a bit of implicit structure: the first element of each "row" is a model number (i.e. some sort of key) and the other elements are parameters (i.e. just data associated to the model number).

{{4154, 0.4, 0.5, 0.01, 0.65}, {4144, 0.3, 0.6, 0.11, 0.54}, {4146, 0.2, 0.7, 0.21, 0.63}, {4147, 0.1, 0.8, 0.31, 0.62}, {4148, 0.11, 0.9, 0.41, 0.61}}

An Association is just a list of key-value pairs (similar to but much more flexible than hash maps or dictionaries in other languages). The representation of a single key-value pair uses a structure called a Rule. You can create a Rule like this: Rule[x,y], but there is a nice shortcut: x->y. Associations are basically just a list of such Rules. So, what I wanted (in my original implementation) is a list that looks like this:

{4154 -> {0.4, 0.5, 0.01, 0.65}, 4144 -> {0.3, 0.6, 0.11, 0.54}, 4146 -> {0.2, 0.7, 0.21, 0.63}, 4147 -> {0.1, 0.8, 0.31, 0.62}, 4148 -> {0.11, 0.9, 0.41, 0.61}}

Then I just wrapped it up in an Association,

modelNumberData=Association[...the list goes here...]

which gives

<|4154 -> {0.4, 0.5, 0.01, 0.65}, 4144 -> {0.3, 0.6, 0.11, 0.54}, 4146 -> {0.2, 0.7, 0.21, 0.63}, 4147 -> {0.1, 0.8, 0.31, 0.62}, 4148 -> {0.11, 0.9, 0.41, 0.61}|>

and bingo, we can access stuff with a key, like this:

modelNumberData[4154]

which gives

{0.4, 0.5, 0.01, 0.65}

The <| and |> are just shorthand for Association.

But I don't want to type in the list ("...the list goes here..." bit) by hand. What I want is to split each "row" into a pair whose first element is the first of the pair and whose "tail" is a list that will be the second element of the pair. And by "pair", I really mean Rule. Mathematica has the functions that I need built in: First and Rest. So, for each row, I want:

Rule[First[row],Rest[row]]

Mathematica also has a function called Map that applies a given function to every element of a list. Well, each row of your data is an element of a list, so if I can just turn that Rule expression into a function, I can Map it over your data. Well, Mathematica has many ways to specify a function, and one is Function (I know, such crazy names, eh?). You can use Function with named arguments, or with positional arguments (look up Slot in the documentation), and I chose positional arguments. Well, I only need one argument, so the positional aspect isn't really apparent, but anyway, it looks like this:

Function[Rule[First[#], Rest[#]]]

Putting this all together, I was able to restructure your data by evaluating this:

Map[Function[Rule[First[#], Rest[#]]], data]

Hmm. That doesn't look like what I originally posted. Well, there are nice shortcuts and syntactic sugar that shorten things. The arrow, -> is infix notation for Rule, so a->b is the same as Rule[a,b]. So, we can simplify our Function: Function[First@# -> Rest@#]. The ampersand is postfix notation for Function, so we can reduce further: (First@# -> Rest@#) &. The parentheses aren't necessary, but they can sometimes help you keep track of things. Finally, Map also has an infix notation: /@, and so we finally arrive at (First@# -> Rest@#) & /@ data.

POSTED BY: Eric Rimbey
Posted 2 years ago

BOOKMARK

First off, here's a lesson: Mathematica has often already thought of what you want to do, and so checking the documentation before you get too far into your own implementation is a good idea. I dug into PopupMenu a bit, and what I implemented above is actually built-in functionality.

We still need structured data, but we don't even need an Association:

keyedData = (Rest@# -> First@#) & /@ data

Now create your popup like this:

PopupMenu[Dynamic[model], keyedData, data[[1, 1]]]

You can skip the third argument if you want; it's just a default.

Now, wherever you evaluate this:

Dynamic[model]

you'll get the parameters (the elements of the row after the model number that was selected). If you look at the documentation for PopupMenu, check out the third and fourth variants.

POSTED BY: Eric Rimbey
Posted 2 years ago

Thank you Eric! Solved my problem, but I must admit that I now have a headache trying to understand all those cryptic symbols in the Association and will need to do some homework! I also still do not understand how the data is structured without invoking that Association and why Dynamic[model] does not match the entries for the model numbers in the table?

POSTED BY: Kevin Ulmer
Posted 2 years ago

Cool, Eric, thank you! Elegant approach. Learned even more! But this assuming a table data format structure?, or can this be used for formats?

POSTED BY: Andrew Meit
Posted 2 years ago

I don't understand the question.

POSTED BY: Eric Rimbey
Posted 2 years ago

If you want to retrieve the parameters, you'll have to "dig in" to the structure of data. That would be easier if you used an Association, so maybe start by structuring your data like this:

keyedData = Association[First@# -> Rest@# & /@ data]

Keep your popup as it is:

PopupMenu[Dynamic[model], modelNumbers]

Now, wherever you want to see the parameters associated with the selected model number, put this expression there:

Dynamic[keyedData[model]]
POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract