这是一个解决方法的示例,它允许您在DataFrame eval函数中使用元组索引。我知道这已经是一个老问题了,但我找不到一个好的答案来回答原始问题。
from pandas import DataFrame, MultiIndex
import re
LEVEL_DELIMITER = "___"
def tuples_to_str(t):
return LEVEL_DELIMITER.join(t)
def str_to_tuples(s):
return tuple(s.split(LEVEL_DELIMITER))
def flatten_mi_var_expression(e):
tuple_re = r'\(.*?,.*?\)'
for tuple_str in re.findall(tuple_re, e):
e = e.replace(tuple_str, tuples_to_str(eval(tuple_str)))
return e
columns = [
('bar', 'one'),
('bar', 'three'),
('flux', 'six'),
('flux', 'three')
]
data = [
[0.627915, 0.507184, 0.690787, 1.166318],
[0.927342, 0.788232, 1.776677, -0.512259],
[1.000000, 1.000000, 1.000000, 0.000000]
]
index = MultiIndex.from_tuples(columns, names=['A', 'B'])
df = DataFrame(data, index=['x', 'y', 'z'], columns=index)
new_col = ('new', 'col')
mi_expression = f"{new_col} = {('flux', 'six')} + {('bar', 'one')}"
mi_cols = df.columns
df.columns = [LEVEL_DELIMITER.join(col) for col in df.columns.values]
flat_expression = flatten_mi_var_expression(mi_expression)
df.eval(flat_expression, inplace=True)
df.columns = MultiIndex.from_tuples(mi_cols.tolist() + [new_col], names=mi_cols.names)
print(df)
这应该提供以下内容。
A bar flux new
B one three six three col
x 0.627915 0.507184 0.690787 1.166318 1.318702
y 0.927342 0.788232 1.776677 -0.512259 2.704019
z 1.000000 1.000000 1.000000 0.000000 2.000000
不确定使用Python eval的安全性(实际上并不需要),但这个例子似乎可以工作。