#python #pandas #dataframe #.loc
#питон #панды #фрейм данных #.loc
Вопрос:
У меня есть набор данных, который я создал, объединив 2 df в столбце «ИМЯ», и теперь у меня есть набор данных большего размера. Чтобы закончить DF, я хочу выполнить некоторую логику, чтобы очистить его.
Требования: я хочу выбрать уникальное «имя», но я хочу сопоставить имя с самым большим объемом продаж подряд, и если после прохождения продажи столбцов, всех строк меньше, чем 10, а затем перейти на призывы столбца и выберите самое строки с наибольшим звонка, и если все звонки в вызывает менее 10 затем перейти к целевой столбец выбрать самую высокую цель. Строки не суммируются.
Вот мой DF:
NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 0 OFFICE 1 2222277 84 170 265 1 OFFICE 1 2222278 26 103 287 2 OFFICE 1 2222278 97 167 288 3 OFFICE 2 2222289 7 167 288 4 OFFICE 2 2222289 3 130 295 5 OFFICE 2 2222289 9 195 257 6 OFFICE 3 1111111 1 2 286 7 OFFICE 3 1111111 5 2 287 8 OFFICE 3 1111112 9 7 230 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298
Вот что я хочу показать в финальном DF:
NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 0 OFFICE 1 2222277 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298
Я думал о том, чтобы решить эту проблему с помощью df.itterows()
Вот что я попробовал:
for n, v in df.iterrows(): if int(v['Sales']) gt; 10: calls = df.loc[(v['NAME'] == v) amp; (int(v['Calls'].max()))] if int(calls['Calls']) gt; 10: target = df.loc[(v['NAME'] == v) amp; (int(v['Target'].max()))] else: print("No match found") else: sales = df.loc[(v['NAME'] == v) amp; (int(v['Sales'].max())]
Тем не менее, я продолжаю получать KeyError: False
сообщения об ошибках. Есть какие-нибудь мысли о том, что я делаю не так?
Комментарии:
1. Под «если «ВЫЗОВОВ» меньше 10″ вы имеете в виду, если «ВЫЗОВОВ», которые были выбраны, меньше 10, от суммы ВЫЗОВОВ для этого НОМЕРА CUSTOMER_SUPPLIER, или что…?
2. хороший вопрос, спасибо за разъяснение. Я ищу строку с наибольшим значением вызова, а не сумму значений.
3. Под «если продажи меньше 10» вы подразумеваете «если самые высокие продажи меньше 10»?
4. да, именно так! если наибольшее значение меньше 10, перейдите к следующему столбцу и проверьте вызовы и следуйте той же логике проверки, чтобы увидеть, меньше ли 10
Ответ №1:
Это не оптимизировано, но должно соответствовать вашим потребностям. Фрагмент кода отправляет каждую NAME
группу туда eval_group()
, где он проверяет наивысший индекс для каждого столбца, пока не будут выполнены критерии продаж, звонков и целей.
Если бы вы хотели оптимизировать, то вы могли бы применить принципы векторизации или параллелизма к eval_group
так называемому методу против всех групп сразу, а не последовательно.
Несколько примечаний, это вернет первую строку, если найдено условие гонки (т. Е. Несколько записей имеют одинаковый максимум во idxmax()
время вызова). Кроме того, я верю в ваш вопрос, что первая строка в желаемом ответе должна OFFICE 1
быть строкой 2, а не 0.
df = pd.read_csv('./data.txt') def eval_group(df, keys) : for key in keys : row_id = df[key].idxmax() if df.loc[row_id][key] gt;= 10 or key == keys[-1] : return row_id row_ids = [] keys = ['Sales','Calls','Target'] for name in df['NAME'].unique().tolist() : condition = df['NAME'] == name row_ids.append( eval_group( df[condition], keys) ) df = df[ df.index.isin(row_ids) ] df NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 2 OFFICE 1 2222278 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298
Комментарии:
1. эй, большое спасибо за этот ответ, я ценю это! Я не смог получить тех же результатов. В результате я получил это. Также, пожалуйста, обратите внимание, что я изменил несколько цифр, но я ожидаю тех же результатов. Я получаю, что офис 1 появляется 3 раза, а офис 2 появляется дважды. Я в точности скопировал вашу формулу и логику
2. Основываясь на логике unique (), вы не должны получать повторяющиеся имена, если у вас нет пробелов вокруг имен. Это сделало бы что-то вроде «Офис 1» и «Офис 1» одинаковыми при печати, но разными при вычислении.
3. ах да, у меня там было несколько свободных мест. вот что это сделало! Спасибо, это здорово!
Ответ №2:
Это занимает несколько шагов, в которых вам нужно построить промежуточные кадры данных, выполнить условное условие и выполнить фильтрацию на основе результата условий:
temp = (df .drop(columns = 'CUSTOMER_SUPPLIER_NUMBER') .groupby('NAME', sort = False) .idxmax() ) # get the booleans for rows less than 10 bools = df.loc(axis=1)['Sales':'Target'].lt(10) # groupby for each NAME bools = bools.groupby(df.NAME, sort = False).all() # conditions buildup condlist = [~bool_check.Sales, ~bool_check.Calls, ~bool_check.Target] choicelist = [temp.Sales, temp.Calls, temp.Target] # you might have to figure out what to use for default indices = np.select(condlist, choicelist, default = temp.Sales) # get matching rows df.loc[indices] NAME CUSTOMER_SUPPLIER_NUMBER Sales Calls Target 2 OFFICE 1 2222278 97 167 288 5 OFFICE 2 2222289 9 195 257 7 OFFICE 3 1111111 5 2 287 9 OFFICE 4 1111171 95 193 299 10 OFFICE 5 1111191 9 193 298