Pandas: строка запроса, в которой имя столбца содержит специальные символы

Я работаю с фреймом данных, который имеет структуру, похожую на следующее:

In[75]: df.head(2)
Out[75]: 
  statusdata             participant_id association  latency response  \
0   complete  CLIENT-TEST-1476362617727       seeya      715  dislike   
1   complete  CLIENT-TEST-1476362617727      welome      800     like   

   stimuli elementdata statusmetadata demo$gender  demo$question2  \
0  Sample B    semi_imp       complete        male              23   
1  Sample C    semi_imp       complete      female              23   

Я хочу иметь возможность запускать строку запроса в столбце demo$gender.

то есть,

df.query("demo$gender=='male'")

Но это имеет проблему с знаком $. Если я заменил знак $ другим разделителем (например, -), проблема не исчезнет. Могу ли я исправить мою строку запроса, чтобы избежать этой проблемы. Я бы предпочел не переименовывать столбцы, так как они тесно связаны с другими частями моего приложения.

Я действительно хочу придерживаться строки запроса, поскольку она предоставляется другим компонентом нашего технологического стека, и создание синтаксического анализатора будет тяжелым лифтом для того, что кажется простой проблемой.

Спасибо заранее.

Ответ 1

Текущая реализация query требует, чтобы строка была допустимым выражением python, поэтому имена столбцов должны быть действительными идентификаторами python. Ваши два варианта переименовывают столбец или используют простой логический фильтр, например:

df[df['demo$gender'] =='male']

Ответ 2

Для заинтересованного здесь простое условие, которое я использовал для выполнения задачи:

# Identify invalid column names
invalid_column_names = [x for x in list(df.columns.values) if not x.isidentifier() ]

# Make replacements in the query and keep track
# NOTE: This method fails if the frame has columns called REPL_0 etc.
replacements = dict()
for cn in invalid_column_names:
    r = 'REPL_'+ str(invalid_column_names.index(cn))
    query = query.replace(cn, r)
    replacements[cn] = r

inv_replacements = {replacements[k] : k for k in replacements.keys()}

df = df.rename(columns=replacements) # Rename the columns
df  = df.query(query) # Carry out query

df = df.rename(columns=inv_replacements)

Это означает идентификацию недопустимых имен столбцов, преобразование запроса и переименование столбцов. Наконец, мы выполняем запрос, а затем переводим имена столбцов назад.