Pandas:查询包含特殊字符的列名的查询字符串

9

我正在处理一个数据框,其结构类似于以下内容:

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'")

但是这个问题涉及到美元符号($)的使用。如果我用另一个分隔符(比如-)代替美元符号,那么问题仍然存在。有没有办法修复我的查询字符串以避免这个问题呢?我不想重命名列名,因为它们与应用程序的其他部分紧密相连。
我真的想坚持使用查询字符串,因为它由我们技术栈的另一个组件提供,并且针对这个看似简单的问题创建解析器需要花费大量时间和精力。
提前感谢您的帮助。
3个回答

15

最新版的pandas中,你可以使用反引号(`)对包含特殊字符的列名进行转义。

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

另外一种可能性是作为流程的先前步骤清理列名,通过使用其他更合适的字符替换特殊字符。

例如:

另一种可能是在您的过程中将列名清理为先前步骤,通过用一些其他更合适的字符替换特殊字符。

例如:

(df
 .rename(columns = lambda value: value.replace('$', '_'))
 .query("demo_gender == 'male'")
) 

1
这个答案现在应该更高 - 可能是pandas后来添加了反引号语法。这是2022年的正确答案;我确认反引号可以用于转义具有特殊字符的列。 - Tommy
谢谢。我已经更改了被接受的答案! - Joe

8

如果您感兴趣,这是我用来完成任务的简单步骤:

# 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)

这意味着需要识别无效的列名,转换查询并重命名列。最后执行查询,然后将列名翻译回来。

感谢@chrisb的答案,它指引了我正确的方向。


3
这应该是被接受的解决方案。顺便说一下,由于您可以链接命令,您也可以编写df.rename(...).query(...).rename(....)来完全避免更改原始df。 - 576i
1
这不再是可接受的解决方案;反引号答案现在可行(在2022年)。 - Tommy
如果查询是一个复杂的查询,包含多个列,这个答案仍然是有用的。例如:(amenity=="fuel") and (fuel:gasoline == "no" or large_vehicles == "no") 我们需要编写一个解析器来单独找出有问题的 fuel:gasoline 并加上反引号。 - undefined

4

目前的 query 实现需要字符串是一个有效的Python表达式,因此列名必须是有效的Python标识符。您有两个选项:重命名列或使用普通布尔过滤器,例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接