Home > Blockchain >  How to pass a single tuple to a function that expects a tuple of tuples
How to pass a single tuple to a function that expects a tuple of tuples

Time:10-10

I'm having some issues with assigning my own x and y values for a plot. By default, x and y are combinations of data frame column names.

For example, var_combinations contains:

(('Cerebrum Volume', 'Cerebellum Volume'), ('Cerebrum Volume', 'Cerebellum Surface Area'), ('Cerebellum Volume', 'Cerebellum Surface Area'))

This works great when left alone, see working code below.

col_names = [list(data.columns)[4], list(data.columns)[3], list(data.columns)[1]]
var_combinations = tuple(itertools.combinations(col_names, 2))


def create_plot(xy=var_combinations, logged=False):
    if not logged:
        fig1, axs1 = plt.subplots(1, (len(xy)), figsize=(16, 5))

        for i, (x, y) in enumerate(xy):
            axs1[i].scatter(data[x], data[y], c=taxon.map(colors), edgecolor='k')
            
            axs1[i].set(
                title=f'Primate {xy[i][0]} against\n{xy[i][1]}',
                xlabel=f'{xy[i][0]}',
                ylabel=f'{xy[i][1]}'
            )
    elif logged: .........

create_plot(var_combinations, logged=False)

However I want to be able to enter my own variable names when calling the function, such as:

create_plot(('Cerebellum Surface Area', 'Cerebrum Volume'), ('etc', 'etc'))

When calling this way I get a ValueError: too many values to unpack (expected 2) when I hit the for loop. How do I fix this problem (and make sure the title/axes labelling and figure plotting works fine)?

Sample data from csv:

Species ,CerebellumSurfaceArea,CerebrumSurfaceArea,CerebellumVolume ,CerebrumVolume,Source,Taxon,,,,,,
Homo_sapiens,,,111.4,1088,MacLeod et al. (2003),Hominidae,,,,,,
Homo_sapiens,,,138.6,1387.1,,Hominidae,,,,,,
Homo_sapiens,,,132,1176.6,,Hominidae,,,,,,
Homo_sapiens,,,139.8,1264.5,,Hominidae,,,,,,
Homo_sapiens,1590,2038,,,Sereno et al. (2020),Hominidae,,,,,,
Homo_sapiens,1128,,,,Sultan and Braitenberg (1993),Hominidae,,,,,,
Pan_troglodytes,345.545,,52.1,383.22,Ashwell (2020),Hominidae,,,,,,
Pan_troglodytes,,,50.1,343.8,MacLeod et al. (2003),Hominidae,,,,,,

CodePudding user response:

  • There are two issues, and they only occur when trying to send a single tuple to the function.
    1. xy should be a tuple of tuples
      • It should be similar to (('CerebrumVolume', 'CerebellumVolume '), ('CerebrumVolume', 'CerebellumSurfaceArea'), ('CerebellumVolume ', 'CerebellumSurfaceArea'))
      • You are giving it ('Cerebellum Surface Area', 'Cerebrum Volume') which is not correctly unpacked.
      • xy=(('CerebrumVolume', 'CerebellumVolume '),) works for sending a single tuple to the function.
    2. When there is only one set of tuples to unpack, plt.subplots creates a single axes instead of an array of axes
      • Use squeeze=False so there will always be an array, even if there is only one axes, and then flatten the array with axes.flatten().
def create_plot(xy=var_combinations, logged=False):
    
    if not logged:
        fig1, axs1 = plt.subplots(1, (len(xy)), figsize=(16, 5), squeeze=False)  # updated with squeeze=False
        axs1 = axs1.flatten()  # added

        for i, (x, y) in enumerate(xy):
            axs1[i].scatter(data[x], data[y], c=data.Taxon.map(colors), edgecolor='k')
            
            axs1[i].set(
                title=f'Primate {xy[i][0]} against\n{xy[i][1]}',
                xlabel=f'{xy[i][0]}',
                ylabel=f'{xy[i][1]}'
            )


data = pd.read_csv('data.csv', usecols=range(7))
col_names = data.columns.to_numpy()[[4, 3, 1]]
var_combinations = tuple(itertools.combinations(col_names, 2))
colors = {'Hominidae': 'tab:green'}

# fix the way a single tuple is passed to the function
create_plot(xy=(('CerebrumVolume', 'CerebellumVolume '),))

enter image description here

  • Related