Как я могу адаптировать и использовать функцию Sumif Excel в python pandas быстрым и pythonic способом?

#python #pandas #dataframe

#python #pandas #dataframe

Вопрос:

Я работаю над проектом, который пытается перенести функции и операции из Excel в python в pandas.

У меня есть много функций SUMIF, которые я пытаюсь воспроизвести в данных. Проблема в том, что я не думаю, что pandas имеет специально аналогичную функцию. У меня может быть выражение Excel, например:

=(SUMIFS('Sheetname'!BI$146:BI$282,'Sheetname'!$B$146:$B$282,$I1836))

Где первый аргумент — это область, которую необходимо суммировать. Вторая область — это диапазон, в котором мы проверяем соответствие критериям, а последний аргумент — это конкретное значение, которое мы ищем.

То, что я делаю прямо сейчас, — это запуск вложенного цикла, который перебирает все строки и столбцы и проверяет, что первая итерация находит совпадающие строки, в то время как внутренний цикл находит совпадающие столбцы. Затем значения суммируются и вводятся в функцию pandas.

Что-то вроде:

table_dict_temp — это таблица, в которую я заполняю значения, в table_temp — это таблица, на которую нужно ссылаться

 for i in range(len(table_dict_temp)):
    cog_loss = table_temp.loc[table_temp[COLUMN OF COMPARISON]==table_dict_temp[COLUMN OF COMPARISON][i]]
    for j in range(10, len(table_dict_temp.columns)):
        cog_loss_temp = cog_loss[table_dict_temp.columns[j]].sum()
        table_dict_temp.iloc[i,j]=cog_loss_temp
 

Проблема, с которой я сталкиваюсь, заключается в том, что это, похоже, непитонический способ сделать это, и это также занимает много времени. Буду признателен за любые советы о том, как я могу написать функцию быстрее!

Комментарии:

1. Я не думаю, что в целом отличная идея пытаться копировать функции Excel в Python, особенно с использованием итеративного решения, как в вашем примере. Это самый медленный метод работы с массивами в Python. Вместо этого лучше разработать новое решение, используя векторизованные функции из Pandas или Numpy.

2. Привет, @Arpit-bajpai. Вам следует избегать использования for i in range(len(iterable)) just use for element in iterable . Кроме того, нельзя использовать циклы и Pandas вместе. Предоставьте некоторые примеры данных, и мы сможем их обработать.

3. Попробуйте использовать что-то вроде библиотеки Kola 2, которая преобразует функции Excel в Python pypi.org/project/koala2

Ответ №1:

Данные примера Excel:

https://support.microsoft.com/en-us/office/sumifs-function-c9e748f5-7ea7-455d-9406-611cebce642b

 Quantity Sold   Product Salesperson
5   Apples  Tom
4   Apples  Sarah
15  Artichokes  Tom
3   Artichokes  Sarah
22  Bananas Tom
12  Bananas Sarah
10  Carrots Tom
33  Carrots Sarah
    
Description

=SUMIFS(A2:A9, B2:B9, "=A*", C2:C9, "Tom")

Adds the number of products that begin with A and were sold by Tom. 
It uses the wildcard character * in Criteria1, "=A*" to look for matching product names in Criteria_range1 B2:B9, 
and looks for the name "Tom" in Criteria_range2 C2:C9. 
It then adds the numbers in Sum_range A2:A9 that meet both conditions. 
The result is 20.

=SUMIFS(A2:A9, B2:B9, "<>Bananas", C2:C9, "Tom")

Adds the number of products that aren’t bananas and are sold by Tom. 
It excludes bananas by using <> in the Criteria1, "<>Bananas", 
and looks for the name "Tom" in Criteria_range2 C2:C9. 
It then adds the numbers in Sum_range A2:A9 that meet both conditions. 
The result is 30.
 

решение pythonic:

 import io
import pandas as pd

data_str = '''
Quantity Sold   Product Salesperson
5   Apples  Tom
4   Apples  Sarah
15  Artichokes  Tom
3   Artichokes  Sarah
22  Bananas Tom
12  Bananas Sarah
10  Carrots Tom
33  Carrots Sarah
'''.strip()

df = pd.read_csv(io.StringIO(data_str), sep='t')

# =SUMIFS(A2:A9, B2:B9, "=A*", C2:C9, "Tom")
cond = True
cond amp;= df['Product'].str.startswith('A')
cond amp;= df['Salesperson'] == 'Tom'
df.loc[cond, 'Quantity Sold'].sum()

# =SUMIFS(A2:A9, B2:B9, "<>Bananas", C2:C9, "Tom")
cond = True
cond amp;= df['Product'] != 'Bananas'
cond amp;= df['Salesperson'] == 'Tom'
df.loc[cond, 'Quantity Sold'].sum()