Как получить сумму по строке с разными наборами столбцов для каждой строки, которая будет суммироваться с помощью Pandas?

Представьте, что у нас есть такой DataFrame:

df = pd.DataFrame(np.array([[284.77, 234.37, 243.8, 84.36, 0., 0., 0., 55.04, 228.2, 181.97, 0., 0.],
                            [13.78, 0., 38.58, 33.16, 0., 38.04, 74.02, 45.74, 27.2, 9.19, 0., 0.],
                            [88.66, 255.72, 323.19, 7.24, 0., 73.38, 45.73, 0., 0., 77.39, 26.57, 279.34],
                            [0., 0., 34.42, 9.16, 0., 43.4, 42.17, 123.69, 60.5, 25.47, 72.32, 7.29],
                            [320.6, 1445.56, 856.23, 371.21, 0., 244.22, 134.58, 631.59, 561.82, 1172.44, 895.68, 186.28],
                            [0., 0., 32.29, 1000.91, 0., 680., 585.46, 466.6, 0., 493.48, 157.1, 125.31]]),
                  columns=[1,2,3,4,5,6,7,8,9,10,11,12])

df['Lists_to_sum'] = [[1,2,3,4],
[4,6,8,9,10,11],
[2],
[3,4,5,6,7,8,9,10,11],
[1,2,3,4,5,6,7,8,9],
[2,3,4,5,6,7,8,9,10,11,12],]
1 2 3 4 5 6 7 8 9 10 11 12 Lists_to_sum 0 284,77 234,37 243,80 84,36 0,00 0,00 0,00 55.04 228,20 181,97 0,00 0,00 [1, 2, 3, 4] 1 13,78 0,00 38,58 33.16 0,00 38.04 74.02 45,74 27.20 9.19 0,00 0,00 [4, 6, 8, 9, 10, 11] 2 88,66 255,72 323,19 7.24 0,00 73,38 45,73 0,00 0,00 77,39 26.57 279,34 [2] 3 0,00 0,00 34,42 9.16 0,00 43.40 42,17 123,69 60,50 25.47 72,32 7.29 [3, 4, 5, 6, 7, 8, 9, 10, 11] 4 320,60 1445,56 856,23 371,21 0,00 244,22 134,58 631,59 561,82 1172,44 895,68 186,28 [1, 2, 3, 4, 5, 6, 7, 8, 9] 5 0,00 0,00 32.29 1000,91 0,00 680,00 585,46 466,60 0,00 493,48 157,10 125,31 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Наша цель — добавить столбец с суммой каждой строки, но есть загвоздка: мы просто хотим сложить столбцы, которые есть в списках каждой строки, представленной в столбце «Lists_to_sum», то есть каждая строка имеет будет добавлен другой набор столбцов

Окончательный DataFrame должен выглядеть так:

1 2 3 4 5 6 7 8 9 10 11 12 Lists_to_sum SUM_per_ROW 0 284,77 234,37 243,80 84,36 0,00 0,00 0,00 55.04 228,20 181,97 0,00 0,00 [1, 2, 3, 4] 847,30 1 13,78 0,00 38,58 33.16 0,00 38.04 74.02 45,74 27.20 9.19 0,00 0,00 [4, 6, 8, 9, 10, 11] 153,33 2 88,66 255,72 323,19 7.24 0,00 73,38 45,73 0,00 0,00 77,39 26.57 279,34 [2] 255,72 3 0,00 0,00 34,42 9.16 0,00 43.40 42,17 123,69 60,50 25.47 72,32 7.29 [3, 4, 5, 6, 7, 8, 9, 10, 11] 411,13 4 320,60 1445,56 856,23 371,21 0,00 244,22 134,58 631,59 561,82 1172,44 895,68 186,28 [1, 2, 3, 4, 5, 6, 7, 8, 9] 4565,81 5 0,00 0,00 32.29 1000,91 0,00 680,00 585,46 466,60 0,00 493,48 157,10 125,31 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 3541,15

Я уже упоминал, что был подвох? На самом деле их два: для решения нам нужна векторизованная производительность.

Я попытался решить эту проблему с помощью наивного подхода, который в некоторой степени сработал: он дает мне желаемые результаты. Но он работает хуже всего, поскольку код перебирает каждую строку. Для крошечного DataFrame, такого как в примере, это нормально, но реализация этого решения на огромном DataFrame с десятками миллионов строк — это уже другая история.

for n,m,i in zip(df.index, df['Lists_to_sum'], range(0, df.shape[0])):  
    df.at[n,'SUM_per_ROW'] = df[m][i:i+1].sum(axis=1)
    print('{} de {}'.format(i+1, df.shape[0]))

Итак, мне интересно, есть ли лучший способ решить эту проблему... Можете ли вы мне помочь?

1
0
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Код

создать условие с помощью explode и get_dummies (и группировать по любому) и логической маскировки (и суммы)

cond = pd.get_dummies(df['Lists_to_sum'].explode()).groupby(level=0).any()
df['SUM_per_ROW'] = df[cond].sum(axis=1)

дф

Отлично, Панда Ким! Он отлично работал с фреймом данных с 1,2 миллионами строк (43 секунды на выполнение). Большое спасибо!

espinafrando 26.06.2024 17:06

Вы можете использовать numpy:

sums = np.zeros(df.shape[0])

for i, indices in enumerate(df["Lists_to_sum"].to_list()):
    sums[i] = df.loc[i, indices].sum()

df["SUM_per_ROW"] = sums
        1        2       3        4    5       6       7       8       9       10      11      12                          Lists_to_sum  SUM_per_ROW
0  284.77   234.37  243.80    84.36  0.0    0.00    0.00   55.04  228.20   181.97    0.00    0.00                          [1, 2, 3, 4]       847.30
1   13.78     0.00   38.58    33.16  0.0   38.04   74.02   45.74   27.20     9.19    0.00    0.00                  [4, 6, 8, 9, 10, 11]       153.33
2   88.66   255.72  323.19     7.24  0.0   73.38   45.73    0.00    0.00    77.39   26.57  279.34                                   [2]       255.72
3    0.00     0.00   34.42     9.16  0.0   43.40   42.17  123.69   60.50    25.47   72.32    7.29         [3, 4, 5, 6, 7, 8, 9, 10, 11]       411.13
4  320.60  1445.56  856.23   371.21  0.0  244.22  134.58  631.59  561.82  1172.44  895.68  186.28           [1, 2, 3, 4, 5, 6, 7, 8, 9]      4565.81
5    0.00     0.00   32.29  1000.91  0.0  680.00  585.46  466.60    0.00   493.48  157.10  125.31  [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]      3541.15

Или pandas.apply:

df["SUM_per_ROW"] = df.apply(
    lambda row: sum(row[col] for col in row["Lists_to_sum"]), axis=1
)
        1        2       3        4    5       6       7       8       9       10      11      12                          Lists_to_sum  SUM_per_ROW
0  284.77   234.37  243.80    84.36  0.0    0.00    0.00   55.04  228.20   181.97    0.00    0.00                          [1, 2, 3, 4]       847.30
1   13.78     0.00   38.58    33.16  0.0   38.04   74.02   45.74   27.20     9.19    0.00    0.00                  [4, 6, 8, 9, 10, 11]       153.33
2   88.66   255.72  323.19     7.24  0.0   73.38   45.73    0.00    0.00    77.39   26.57  279.34                                   [2]       255.72
3    0.00     0.00   34.42     9.16  0.0   43.40   42.17  123.69   60.50    25.47   72.32    7.29         [3, 4, 5, 6, 7, 8, 9, 10, 11]       411.13
4  320.60  1445.56  856.23   371.21  0.0  244.22  134.58  631.59  561.82  1172.44  895.68  186.28           [1, 2, 3, 4, 5, 6, 7, 8, 9]      4565.81
5    0.00     0.00   32.29  1000.91  0.0  680.00  585.46  466.60    0.00   493.48  157.10  125.31  [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]      3541.15

Другие вопросы по теме