#python #pandas
#python #панды
Вопрос:
У меня есть df :
Это выглядит так:
A Wave Dept Ratio
1 1 1 A 10
2 4 1 A 6
3 7 2 A 3
4 2 2 A 4
5 6 2 B 9
6 5 2 B 7
7 5 1 B 12
8 5 1 B 4
9 5 2 C 9
10 5 1 C 3
11 5 1 C 4
12 5 2 C 7
В настоящее время я группирую данные по Dept
и проверяю каждую строку Ratio
на соответствие всем другим соотношениям с тем же отделом и увеличиваю количество, если значение соотношения превышает пороговое значение.
Код для этого выглядит следующим образом:
import pandas as pd
lowerThreshold=1.2
def main():
print()
df = pd.DataFrame([
[1, 1, 'A', 10],
[4, 1 ,'A', 6],
[7, 2 ,'A', 3],
[2, 2 ,'A', 4],
[6, 2 ,'B', 9],
[5, 2 ,'B', 7],
[5, 1 ,'B', 12],
[5, 1 ,'B', 4],
[5, 2 ,'C', 9],
[5, 1 ,'C', 3],
[5, 1 ,'C', 4],
[5, 2 ,'C', 7]
],
index=['1', '2', '3','4','5','6','7','8','9','10','11','12'],
columns=['A', 'Wave', 'Dept', 'Ratio'])
print('df input:')
print(df)
df['Output']=df.groupby('Dept')['Ratio'].transform(lambda dept: compareLower(dept.values,lowerThreshold))
df[df['Wave'] <= 3]
print()
print('df - output')
print(df)
def compareLower(dept,lowerThreshold):
print('x:',dept)
#print('y:',y)
return (dept[:,None] < lowerThreshold*dept).sum(-1)
Вывод для этого выглядит следующим образом:
A Wave Dept Ratio Output
1 1 1 A 10 1
2 4 1 A 6 2
3 7 2 A 3 4
4 2 2 A 4 3
5 6 2 B 9 2
6 5 2 B 7 3
7 5 1 B 12 1
8 5 1 B 4 4
9 5 2 C 9 1
10 5 1 C 3 4
11 5 1 C 4 3
12 5 2 C 7 2
Теперь я хотел бы добавить дополнительную группировку , которая также группируется Wave
. Я хотел бы включать в группу только в том случае, если Wave
значения набора данных равны или меньше волны записи. Например, если волна записей равна 1, а отдел равен A, то группировка будет включать только записи, у которых волна равна или меньше 1и значение Dept, равное A. Если волна равна 2, а Dept равно A, то группировка будет включать любую запись, у которой значение Dept равно A, а волна равна или меньше 2 (таким образом, включая записи со значением волны 1, а также 2).
Таким образом, пересмотренный вывод будет выглядеть следующим образом:
A Wave Dept Ratio Output
1 1 1 A 10 0
2 4 1 A 6 1
3 7 2 A 3 3
4 2 2 A 4 2
5 6 2 B 9 1
6 5 2 B 7 2
7 5 1 B 12 0
8 5 1 B 4 1
9 5 2 C 9 0
10 5 1 C 3 1
11 5 1 C 4 0
12 5 2 C 7 1
Я попытался добавить новую группировку:
df['Output']=df.groupby('Dept','Wave<=??')['Wave','Ratio'].transform(lambda x: compareLower(x.values,lowerThreshold))
Но я не знаю, как сделать волну динамической (поскольку каждая строка имеет разное значение волны). Также возможно более 2 волн.
Комментарии:
1. Это ваше
Wave
единственное1
и2
или будут более высокие значения?2. @QuangHoang спасибо — существует потенциал для более высоких значений Wave
3. Кроме того, ваш ожидаемый результат начинается с
1
или с0
самого высокого?4. Спасибо — Wave начнется с 1 и увеличится
Ответ №1:
Давайте попробуем вашу логику здесь, заполнив Output
столбцы рейтингами, когда мы удаляем Wave
один за другим:
waves = sorted(set(df['Wave']))[::-1]
df['Output'] = np.nan
for thresh in waves:
df['Output'] = (df[df['Wave'].le(thresh)].groupby('Dept')
.Ratio.rank(ascending=False).sub(1)
.reindex(df.index)
.fillna(df['Output'])
)
Вывод:
A Wave Dept Ratio Output
1 1 1 A 10 0.0
2 4 1 A 6 1.0
3 7 2 A 3 3.0
4 2 2 A 4 2.0
5 6 2 B 9 1.0
6 5 2 B 7 2.0
7 5 1 B 12 0.0
8 5 1 B 4 1.0
9 5 2 C 9 0.0
10 5 1 C 3 1.0
11 5 1 C 4 0.0
12 5 2 C 7 1.0