Python Forum
Looking for Eval alternative
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Looking for Eval alternative
#1
My goal is to put together a pandas column search function based on how many columns are present.
import pandas as pd

head_list = 'Segment', 'Country', 'Discount Band'
search_vals = 'Government', 'France', 1899
data = [['Government', 'France', 1899], ['Midmarket', 'France', 1899], ['Midmarket', 'Mexico', 1899]]
df = pd.DataFrame(data, columns = ['Segment', 'Country', 'Discount Band'])
if len(head_list) > 1:
    exec_str = 'df['
    for x in head_list:
        if head_list.index(x) != (len(head_list) - 1):
            exec_str += '(df[head_list[' + str(head_list.index(x)) + ']] == search_vals[' + str(head_list.index(x)) + ']) &'
        else:
            exec_str += '(df[head_list[' + str(head_list.index(x)) + ']] == search_vals[' + str(head_list.index(x)) + '])]'

print(eval(exec_str))
^^ So far i was using something like this but was reading that eval isn't suggested when accepting user input. Does anyone have suggestions for how to handle this differently?
Would your suggestion work if searching the below in the example data frame above?
head_list = 'Segment', 'Country'
search_vals = 'Government', 'France'
Reply
#2
Not sure, but you are probably trying to do something like this:

import pandas as pd
 
head_list = 'Segment', 'Country', 'Discount_Band'
search_vals = 'Government', 'France', 1899
data = [['Government', 'France', 1899], ['Midmarket', 'France', 1899], ['Midmarket', 'Mexico', 1899]]
df = pd.DataFrame(data, columns = ['Segment', 'Country', 'Discount_Band'])
query = '&'.join([f'({a} == "{b}")' for a, b in zip(head_list, search_vals)])
df.query(query)
Check out query method. It would be better if you avoid using of column names with spaces.
Reply
#3
Thank you scidam! That answer helped me on a few levels.
i was unaware of the query method but am now reading an excellent article from PythonDataScienceHandbook about eval and query
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020