1

Not sure how to word this, but I'm trying to reference an f string within another f string.

I have lists, which could be variable in length.

list_a = ['a', 'b', 'c']
list_b = ['a', 'b', 'c', 'd']

these are dataframe column names, which I'm trying to reference and pull the value of a specific row like so:

desc = " \n".join(
                    [
                        f"- {df.iloc[i]['a']} | {df.iloc[i]['b']} | plus some additional text here"
                        for i in df[0:3].index
                    ]
                )

but I need the description to be variable, depending on if I am looping through list_a or list_b.

I've tried something like this:

attempt = ' | '.join(f"{{df[i][{j}]}}" for j in list_a)
desc = " \n".join(
                    [
                        f"- {attempt} | plus some additional text here"
                        for i in df[0:3].index
                    ]
                )

but instead of looking up the value of the dataframe, it prints the string:

  • {df.iloc[i]['a']} | {df.iloc[i]['b']} ... plus some additional text here
  • {df.iloc[i]['a']} | {df.iloc[i]['b']} ... plus some additional text here

what am I missing here?

  • Why do you need an f-string for `attempt` at all? `attempt = ' | '.join(df[i][j] for j in list_a)` should suffice. – chepner Feb 07 '23 at 22:22
  • If the logic seems confusing, try writing this without f-strings first. Maybe you can refactor that into simpler code that uses f-strings, maybe not. – chepner Feb 07 '23 at 22:23
  • @chepner yeah I don't know, I think I was staring at this for too long and overcomplicating it. this worked, thanks for the help. ```desc = " \n".join( [ f"- {' | '.join(df[i][j] for j in list_a)} | plus some additional text here" for i in df[0:3].index ] )``` – acrobaticrock Feb 07 '23 at 22:43
  • 1
    Are the columns strings? can you supply a minimal example of the DataFrame: [How to make good reproducible pandas examples](https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples). – wwii Feb 07 '23 at 22:59
  • Seems like `[thing[list_b].str.cat(sep=' | ') for index,thing in df.iterrows()]` is very close to what you are trying to do. WHY do you need to use f-strings? – wwii Feb 07 '23 at 23:19
  • Is `pd.DataFrame({'a':list('qwer'),'b':list('tyui'),'c':list('opas'),'d':list('dfgh')})` a reasonable facsimile of your DataFrame? – wwii Feb 07 '23 at 23:52

1 Answers1

1

It's because the attempt is just a string and its content is not parsed as a part of a f-string in the second f-string. So if you want the attempt to be parsed as a part of a f-string, use eval() like the following.

attempt = ' | '.join(f'{{df[i][{j}]}}' for j in list_a)
desc = ' \n'.join(
    eval(f'f"- {attempt} ..."')
        for i in df[0:3].index
)

But it will be more simple and efficient to use str.format() like this.

desc = ' \n'.join(
    '- {} | ...'.format(' | '.join(f'{df[i][j]}' for j in list_a))
        for i in df[0:3].index
)
relent95
  • 3,703
  • 1
  • 14
  • 17