Create dynamic variable from returned value / variable

1189
6
Jump to solution
06-23-2022 08:46 PM
CPoynter
Occasional Contributor III

Hi,

Trying to work out how to use a returned value to make a new dynamic variable name:

returned value equals: 'Red' which is coming from another variable named {colour}.

new variable name created equals: 'Red' + '_dom' = Red_dom

I read about global() and local() but not sure if they are the correct approach.

When I try 'Red' + '_dom' I get a string error returned by system.

I will actually need something like {colour} + '_dom' to be the new variable name as {colour} changes within a loop.

Regards,

Craig

0 Kudos
1 Solution

Accepted Solutions
Luke_Pinner
MVP Regular Contributor

That sort of hackery is not very pythonic.  What you want is called a dictionary. 

 

 

colours = {}
colour = "red"
colours[f"{colour}_dom"] = "anothervalue"

print(list(colours.keys()))

# ['red_dom']

 

 

View solution in original post

6 Replies
LongDinh
Occasional Contributor II

You can use __getattr__() and __setattr__() built in methods on global/local namespaces to get/set variables by string name on an object or module.

See: https://docs.python.org/3.7/library/functions.html#getattr and https://docs.python.org/3.7/library/functions.html#setattr 

0 Kudos
Luke_Pinner
MVP Regular Contributor

That sort of hackery is not very pythonic.  What you want is called a dictionary. 

 

 

colours = {}
colour = "red"
colours[f"{colour}_dom"] = "anothervalue"

print(list(colours.keys()))

# ['red_dom']

 

 

CPoynter
Occasional Contributor III

If

print(colours[f"{colour}_dom"]) returns

anothervalue

and

print(colours) returns 

{'red_dom': 'anothervalue'}

 How do return as 'red_dom' = 'anothervalue', so from my loop I can list the variable 'red_dom' etc. to equal the returned value such as:

'Name', 'Car', 'red_dom', 'blue_dom, 'green_dom'

where 'red_dom', 'blue_dom, 'green_dom' are calculated number of coloured cars for example.

0 Kudos
Luke_Pinner
MVP Regular Contributor

Your use case is a bit unclear to me Craig, could you add a bit of pseudo-code to try and illustrate what you're trying to do?

But if what I think you're trying to do is correct, the following might help...?

# Just some simple dummy data,
# you could have a car class or pandas dataframe with car colour, make, model, etc... details
cars = ["red", "red", "blue", "white", "white", "red", "blue", "white"]

car_colours = {}

for colour in cars:
    car_colours[colour] = car_colours.get(colour, 0) + 1

    # could also use
    try:
        car_colours[colour] += 1
    except KeyError:
        car_colours[colour] = 1

# Now show all colours and how many cars were that colour
for colour, count in car_colours.items():
    print(f"There were {count} {colour} cars.")

# Now just print how many red and orange cars:
print(f"There were {car_colours['red']} red cars.")
print(f"There were {car_colours.get('orange', 0)} orange cars.")
# I use .get instead of ["key"] as I know there's no orange cars and would otherwise get a KeyError

Output:

There were 6 red cars.
There were 4 blue cars.
There were 6 white cars.
There were 6 red cars.
There were 0 orange cars.
0 Kudos
CPoynter
Occasional Contributor III

Hi Luke,

Here is the type of outcome I am after (not actual data but similar scenario):

CraigPoynter_0-1657169047807.png

I have a large table of data (let's say car sales by dealer). I have done the stats to work out which vehicle type and style was sold in each colour. I know which is the maximum or dominant colour, and I am trying to capture that into a CSV document based on a ranking of colour.

In the script you have been addressing, I am trying to capture the dominant colour under each vehicle style so that my CSV output 'write' is something like:

csv_data = dealer, car, sedan_dom, wagon_dom, convertible_dom

Section of my script that I am trying to capture final value of sedan_dom, wagon_dom and convertible_dom.

if sorted_output[0][1] == '0': (captures null/zero tuples)
     dom = '0'
else:
     most_significant_output = sorted_output[0] (captures ranked dominant tuple)
     dom = most_significant_output[0] (section where I need a variable in the loop to                      be named sedan_dom, wagon_dom, convertible_dom)

Hope that might clear up what I am attempting to do. Might have just made it more confusing.

0 Kudos
Luke_Pinner
MVP Regular Contributor

You don't need "variable" variable names. Just rename the columns before you write out to CSV.

e.g.

columns = ["sedan", "wagon", "convertible"] 
new_columns = [f"{c}_dom" for c in columns]

 

Here's a pandas version:

import pandas as pd
from io import StringIO  # not required if reading csv from file

# Dummy csv to demo, can also read from csv file
csv = """dealer,car,sedan,wagon,convertible, junk
A,Ford,Red,0,Green, None
A,GMC,Blue,Red,0, None
B,BMW,Green,0,Red, None
B,Ford,0,Blue,Red, None
C,BMW,0,Green,0, None
C,GMC,Red,Blue,Red, None
D,GMC,Red,Blue,Blue, None
D,GMC,Red,Blue,0, None
"""

columns = ["sedan", "wagon", "convertible"]  # ignore the junk etc, columns that aren't of interest
dom_columns = {c: f"{c}_dom" for c in columns}

df = pd.read_csv(StringIO(csv))  # or df = pd.read_csv(r"path/to/csv")
dom_df = df[columns].mode().rename(columns=dom_columns)
dom_df.to_csv("dom.csv", index=False)

 

0 Kudos