Возможно, это не самое элегантное решение, но оно работает.Сначала давайте найдем общие ключи:
import numpy as np
keys = np.intersect1d(df.index.str.extract("(.+)_value").dropna(),
df.index.str.extract("(.+)_ref").dropna())
#array(['a', 'b'], dtype=object)
Затем выберите соответствующие ссылки и значения:
refs = df.loc[keys + "_ref"]
values = df.loc[keys +"_value"]
Сделайте копию каждого кадра данных и назначьте им ключи в виде индексов:
values1 = values.copy()
values1.index = keys
refs1 = refs.copy()
refs1.index = keys
Выполните деление и обновите индексы еще раз:
ratios = values1 / refs1
ratios.index += "_value" + "/" + ratios.index + "_ref"
ratios1 = refs1 / values1
ratios1.index += "_ref" + "/" + ratios1.index + "_value"
Соберите все вместе и сортируйте:
pd.concat([refs, values, ratios, ratios1]).sort_index()
# 1 2
#a_ref 4.0 2.000000
#a_ref/a_value 2.0 0.250000
#a_value 2.0 8.000000
#a_value/a_ref 0.5 4.000000
#b_ref 3.0 15.000000
#b_ref/b_value 0.5 1.500000
#b_value 6.0 10.000000
#b_value/b_ref 2.0 0.666667