Creating multiple variables at once - how to?

Hi DQ community, first post of 2020 - hence a well deserved happy new year :slight_smile:
I’ve got a question that is bugging me. In DQ exercises I often find myself with the need of defining mutiple variables, a type-intensive task that is results in very verbose code - I’d like to understand how I can do this in a bit more elegant and efficient way.

Take for instance
From 5 dataframes, we are asked to generate 5 frequency distributions on a specific column of the df.

the proposed answer is:

rookies = wnba[wnba['Exp_ordinal'] == 'Rookie']
little_xp = wnba[wnba['Exp_ordinal'] == 'Little experience']
experienced = wnba[wnba['Exp_ordinal'] == 'Experienced']
very_xp = wnba[wnba['Exp_ordinal'] == 'Very experienced']
veterans =  wnba[wnba['Exp_ordinal'] == 'Veteran']
rookie_distro = rookies['Pos'].value_counts()
little_xp_distro = little_xp['Pos'].value_counts()
experienced_distro = experienced['Pos'].value_counts()
very_xp_distro = very_xp['Pos'].value_counts()
veteran_distro = veterans['Pos'].value_counts()

I was able to come up with something shorter with list comprehension:

categories = [rookies, little_xp, experienced, very_xp, veterans]

rookies_distro, little_xp_distro, experienced_distro, very_xp_distro, veteran_distro = [cat["Pos"].value_counts() for cat in categories]

But even in this case, I have to write down all the variables, whilst I’d like to be able to define them with something like the below (in pseudocode).

for i in ['rookies', 'little_xp', 'experienced', 'very_xp', 'veterans']:
    my_variable_names = "{}_distro".format(i)

I think it is related to generators, but having some guidance would be helpful. Or, in a more widespread sense, what would be the pythonic way in creating multiple variables that have the same structure behind them?
THanks! :slight_smile:

1 Like

Hey, Nick.

It should be possible to create multiple variables programmatically by adding them to the vars() dictionary. You can see an example below, but I suggest you keep reading and come back to the example later.

See an example here

This isn’t recommended:

>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}

The vars() dictionary holds the variables created thus far.

>>> x=3
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 3}

We see it now includes x with the value 3. Let’s try manually adding a variable to the dictionary

>>> vars()["y"] = 5
>>> x+y

It worked!

However, the proper (and Pythonic) way to do it is by simply creating a dictionary where the keys will hold the desired variable name as a string, and the value will be the value you intended the variable to have.

You’ll then have to access the dictionary in order to get to the value, instead of having it as a proper variable name.

In this screen, this possibility was basically taken from you because we start out by immediately defining five different variables manually.

1 Like

Thanks Bruno! Didn’t know about the vars() dict.
So I’d need to to something like the below?

categories = [rookies, little_xp, experienced, very_xp, veteran]

new_dict = {}
for cat in categories:
    key = "{}_distro".format(cat)
    values = wnba[wnba["Exp_ordinal"] == cat]
    new_dict[key] = value

This is not going to help in terms of DQ answer checking but it’d be good to know if it goes in the right direction as for python standards. :slight_smile:

Thanks for your help bruno!

1 Like

That’s right!

Also right :slight_smile:

You’re welcome.

You can explore eval() and exec() of python to turn strings which you generate dynamically to executable code. Some people use eval() to control which of a few similarly named functions should be called

1 Like