Не ясно, в чем ваша проблема на самом деле. Потому что в коде, который вы указали в вопросе, нет вложенных циклов for. Вы имеете в виду вложенные циклы для всех комбинаций значений Name
, Color
и Brand
? Если это так, вам не нужно писать какие-либо циклы. Просто используйте pandas
означает:
df2 = df1.groupby(['Name', 'Color', 'Brand']).agg({'Value': 'sum'})
Да, одна строка для их вычисления. Как group by
в SQL. Например, num22
- это df2.loc[('Name 0', 'Color 2', 'Brand 2'), 'Value']
.
В случае немного более сложных расчетов
df3 = df1.groupby(['Name', 'Color', 'Brand']).agg({'Value': ['count', 'sum']})
num22
- это df3.loc[('Name 0', 'Color 2', 'Brand 2'), ('Value', 'sum')]
.
Аргумент
.agg(...)
- это словарь, в котором вы указываете, какие столбцы вы хотите обработать и какую статистику вы хотите получить.
Попробуйте так и скажите, не понимаю ли я вашу проблему.
EDIT
Рассмотрим следующий код:
# 1. original code with nested loops
# includes slight correction (+1 in range(...) and zeros(...) functions)
def f_1(df1):
end_values = np.zeros(nName + 1)
for iName in range(nName + 1):
y = 0
for iColor in range(nColor + 1):
x = np.zeros(nBrand + 1)
for iBrand in range(nBrand + 1):
x[iBrand] = np.nansum(df1[((df1['Name'] == 'Name {}'.format(iName)) & (df1['Color'] == 'Color {}'.format(iColor)) & (df1['Brand'] == 'Brand {}'.format(iBrand)))]['Value'])
y = y + x[0] + 1.5 * x[1] + 3 * x[0] * x[2]
end_values[iName] = y
return end_values
# 3. new code - supportive function to calculate result for brands
def f_2_suppport(srs):
cnt = {k: v for k, v in zip(srs.index.get_level_values(2), srs)}
a = cnt.get('Brand 0', 0)
b = cnt.get('Brand 1', 0)
c = cnt.get('Brand 2', 0)
return a + 1.5 * b + 3 * a * c
# 2. new code - main function with pandas groupby/agg
def f_2(df1):
return (
df1
.groupby(['Name', 'Color', 'Brand'])
.agg({'Value': 'sum'})
.groupby(['Name', 'Color'])
.agg({'Value': lambda x: f_2_suppport(x)})
.groupby('Name')
.agg({'Value': 'sum'}))
if __name__ == '__main__':
print(f_1(df1))
print(f_2(df1))
Выход:
[28735057. 26111382. 28304153.5 15495841. 15915862.5 13884354.5
21172873. 27342470.5 29403143. 38212958.5 37504605. ]
Value
Name
Name 0 28735057.0
Name 1 26111382.0
Name 10 37504605.0
Name 2 28304153.5
Name 3 15495841.0
Name 4 15915862.5
Name 5 13884354.5
Name 6 21172873.0
Name 7 27342470.5
Name 8 29403143.0
Name 9 38212958.5
Время выполнения на моей машине:
%timeit f_1(df1)
1.07 s ± 736 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit f_2(df1)
35.2 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Итак groupby
+ agg
сделать расчет примерно в 30 раз быстрее.