Я группирую свой набор данных по столбцу A, а затем хотел бы взять минимальное значение в столбце B и соответствующее значение в столбце C.
data = pd.DataFrame({'A': [1, 2], 'B':[ 2, 4], 'C':[10, 4]})
data
A B C
0 1 4 3
1 1 5 4
2 1 2 10
3 2 7 2
4 2 4 4
5 2 6 6
и я хотел бы получить:
A B C
0 1 2 10
1 2 4 4
На данный момент я группирую по A и создаю значение, которое указывает мне строки, которые я буду хранить в своем наборе данных:
a = data.groupby('A').min()
a['A'] = a.index
to_keep = [str(x[0]) + str(x[1]) for x in a[['A', 'B']].values]
data['id'] = data['A'].astype(str) + data['B'].astype('str')
data[data['id'].isin(to_keep)]
Я уверен, что есть гораздо более прямой способ сделать это. Я видел здесь много ответов, в которых используется мультииндексация, но я хотел бы сделать это, не добавляя мультииндекс в свой фрейм данных. Спасибо за помощь.






Я чувствую, что ты слишком много думаешь об этом. Просто используйте groupby и idxmin:
df.loc[df.groupby('A').B.idxmin()]
A B C
2 1 2 10
4 2 4 4
df.loc[df.groupby('A').B.idxmin()].reset_index(drop=True)
A B C
0 1 2 10
1 2 4 4
Я пробую это решение, но с pandas 1.0.0 я получаю сообщение об ошибке: Passing list-likes to .loc or [] with any missing labels is no longer supported . @ cs95 у вас есть предложения, как это исправить?
@ cs95 это приводит к одной строке на A, что, если есть несколько строк с минимальным значением для каждого из значений в A. что-то вроде всех студентов с минимальными оценками по естественным наукам.
Была аналогичная ситуация, но с более сложным заголовком столбца (например, "В знач"), и в этом случае это необходимо:
df.loc[df.groupby('A')['B val'].idxmin()]
Я нашел ответ немного более многословный, но намного эффективнее:
Это пример набора данных:
data = pd.DataFrame({'A': [1,1,1,2,2,2], 'B':[4,5,2,7,4,6], 'C':[3,4,10,2,4,6]})
data
Out:
A B C
0 1 4 3
1 1 5 4
2 1 2 10
3 2 7 2
4 2 4 4
5 2 6 6
Сначала мы получим минимальные значения в серии из операции groupby:
min_value = data.groupby('A').B.min()
min_value
Out:
A
1 2
2 4
Name: B, dtype: int64
Затем мы объединяем результат этой серии с исходным фреймом данных.
data = data.merge(min_value, on='A',suffixes=('', '_min'))
data
Out:
A B C B_min
0 1 4 3 2
1 1 5 4 2
2 1 2 10 2
3 2 7 2 4
4 2 4 4 4
5 2 6 6 4
Наконец, мы получаем только те строки, где B равно B_min, и отбрасываем B_min, так как он нам больше не нужен.
data = data[data.B==data.B_min].drop('B_min', axis=1)
data
Out:
A B C
2 1 2 10
4 2 4 4
Я протестировал его на очень больших наборах данных, и это был единственный способ заставить его работать в разумные сроки.
Спасибо! который работает с простой линией. Действительно, я не знал, что существует метод idxmin().