Формирование вложенного списка и вычисление суммы полей
В базе данных записи хранятся в таком виде:

Я пишу функцию, которая будет рассчитывать сумму заданных значений для разных переменных clu (например, q и е). То есть сначала определяется, какие значения name соответствуют значению e (это three и four). Далее идет обращение к словарю "e", в котором хранятся определенные значения, соответсвующие разным name. Функция должна определить, что для группы e необходимо сложить значения ключей "name" three и four и выдать результат.
Пример словаря e:
{'one': {'u_mean': 4.25, 'c_mean': 4.25}, 'three': {'u_mean': 4.5, 'c_mean': 4.5}, 'two': {'u_mean': 4.583333333333334, 'c_mean': 4.583333333333334}, 'four': {'u_mean': 4.5625, 'c_mean': 4.5625}, 'five': {'u_mean': 4.65, 'c_mean': 4.65}}
Результат должен быть такой:
{'e': {'u_mean': 4.531, 'c_mean': 4.531}, 'q': {'u_mean': 4.49443, 'c_mean': 4.49443}}
То есть складываются поля все u_mean и находится их среднее, и также складываются.
Полный код моей функции:
def group_names():
st, c_clus, n_names = [], [], []
for h in Utilizations.objects.values('clu', 'name', 'a', 'b'):
st.append((h.get('clu'), h.get('name'), h.get('a'), h.get('b')))
c_clus.append(h.get('clu'))
n_names.append(h.get('name'))
"""получение названий"""
names, clus = [], []
for nam in n_names:
if nam not in names:
names.append(nam)
for cl in c_clus:
if cl not in clus:
clus.append(cl)
clu, e = {}, {}
u_load, u_max = {}, {}
mean_all, u_load_mean, u_max_mean = 0, 0, 0
for nam in names:
hs = Utilizations.objects.filter(name=nam)
o, p = 0, 0
for h in hs:
o += h.a
p += h.b
u_load[nam] = o / 2 + 1
u_max[nam] = p / 2 + 1
u_max_mean = mean(u_max.values())
u_load_mean = mean(u_load.values())
mean_all = (u_max_mean + u_load_mean) / 2
e[nam] = {'u_mean': mean_all, 'c_mean': mean_all}
for cl in clus:
for nam in names:
s = Utilizations.objects.filter(name=nam, clu=cl)
for h in hs:
clu[nam] = cl
return clu
Получается сгруппировать в таком виде: {'one': 'q', 'two': 'q', 'five': 'q', 'three': 'e', 'four': 'e'}
А как дальше не знаю(
Ответы (1 шт):
Ну, поскольку вразумительного ответа на вопрос, а что-же действительно нужно ТС не последовало, пришлось писать универсальное решение.
По сути оно состоит из двух частей. Часть первая - собираем два универсальных DataFrame, отдельно для признака "a" и отдельно для признака "b". (Тестовые данные немного расширены, что-бы захватить больше различных возможных случаев)
import pandas as pd
db=pd.DataFrame({'a':[8,10,7,20,7,6,6,1,2,3,4,5,7],
'b':[7,4,6,8,6,9,10,1,2,3,4,5,7],
'clu':['e','e','e','e','q','q','q','t','t','t','t','t','t'],
'name':['three','four','three','four','one','two','five',
'one','two','three','four','five','seven']})
clu_list=db.clu.unique()
name_list=db.name.unique()
db_a=pd.DataFrame(index=name_list)
db_b=pd.DataFrame(index=name_list)
for clu_ex in clu_list:
db_a[clu_ex] = db.loc[db.clu==clu_ex].groupby(['name'])['a'].mean()
db_b[clu_ex] = db.loc[db.clu==clu_ex].groupby(['name'])['b'].mean()
Имея эти DataFrame легко решаем разные варианты задачи.
Во-первых, вариант в котором для каждого 'clu' строиться свой словарь, которые в свою очередь объединяются словарь словарей.
d_l={}
for clu_ex in clu_list:
d_r={}
for row in name_list:
a_p=db_a.loc[row][clu_ex]
b_p=db_b.loc[row][clu_ex]
d_r1={}
if pd.notna(a_p):
d_r1['u_mean']=a_p
if pd.notna(b_p):
d_r1['c_mean']=b_p
if pd.notna(a_p) and pd.notna(b_p):
d_r[row]=d_r1
d_l[clu_ex]=d_r
print (d_l)
В результате получаем вот это:
{'e': {'three': {'u_mean': 7.5, 'c_mean': 6.5}, 'four': {'u_mean': 15.0,
'c_mean': 6.0}},
'q': {'one': {'u_mean': 7.0, 'c_mean': 6.0}, 'two': {'u_mean': 6.0, 'c_mean':
9.0}, 'five': {'u_mean': 6.0, 'c_mean': 10.0}},
't': {'three': {'u_mean': 3.0, 'c_mean': 3.0}, 'four': {'u_mean': 4.0,
'c_mean': 4.0}, 'one': {'u_mean': 1.0, 'c_mean': 1.0}, 'two': {'u_mean': 2.0,
'c_mean': 2.0}, 'five': {'u_mean': 5.0, 'c_mean': 5.0}, 'seven': {'u_mean':
7.0, 'c_mean': 7.0}}
}
Во-вторых, если нужно построить общий словарь по каждому из значений переменной clu, то из тех-же промежуточных DataFrame они получаются следующим образом.
d_l={}
for clu_ex in clu_list:
d_r1={}
d_r1['u_mean']=db_a.mean()[clu_ex]
d_r1['c_mean']=db_b.mean()[clu_ex]
d_l[clu_ex]=d_r1
print (d_l)
В итоге получаем:
{'e': {'u_mean': 11.25, 'c_mean': 6.25},
'q': {'u_mean': 6.333333333333333, 'c_mean': 8.333333333333334},
't': {'u_mean': 3.6666666666666665, 'c_mean': 3.6666666666666665}}
В-третьих, если надо данные выдать по параметру name (что вроде бы пытается сделать ТС в своем коде), то выглядеть это будет так:
d_l={} db_a.mean(axis=1) for name_ex in name_list: d_r1={} d_r1['u_mean']=db_a.mean(axis=1)[name_ex] d_r1['c_mean']=db_b.mean(axis=1)[name_ex] d_l[name_ex]=d_r1 print (d_l)
И соответствующий результат:
{'three':{'u_mean': 5.25, 'c_mean': 4.75},
'four': {'u_mean': 9.5, 'c_mean': 5.0},
'one': {'u_mean': 4.0, 'c_mean': 3.5},
'two': {'u_mean': 4.0, 'c_mean': 5.5},
'five': {'u_mean': 5.5, 'c_mean': 7.5},
'seven':{'u_mean': 7.0, 'c_mean': 7.0}}
Разумеется, если универсальность не нужна, то задача существенно упрощается. Но надеюсь, такой тюнинг, а так-же рихтовку в случае, если что-то в условии осталось понято не верно, ТС сможет сделать самостоятельно. Ну, или задать дополнительные вопросы.