2016-01-27 3 views
3

У меня есть DataFrame ...Панды установленное значение в GroupBy

>>> df = pd.DataFrame({ 
...   'letters' : ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'], 
...   'is_min' : np.zeros(9), 
...   'numbers' : np.random.randn(9) 
... }) 

    is_min letters numbers 
0 0  a  0.322499 
1 0  a  -0.196617 
2 0  a  -1.194251 
3 0  b  1.005323 
4 0  b  -0.186364 
5 0  b  -1.886273 
6 0  c  0.014960 
7 0  c  -0.832713 
8 0  c  0.689531 

Я хотел бы установить «» is_min седловины 1, если «число» является минимальное значение по колонке «букв». Я попытался это и чувствую, что я близко ...

>>> df.groupby('letters')['numbers'].transform('idxmin') 

0 2 
1 2 
2 2 
3 5 
4 5 
5 5 
6 7 
7 7 
8 7 
dtype: int64 

Я с трудом соединяя точки, чтобы установить Валя из «is_min» до 1.

ответ

4

Проходят строк для loc и установить колонки:

In [34]: 
df.loc[df.groupby('letters')['numbers'].transform('idxmin'), 'is_min']=1 
df 

Out[34]: 
    is_min letters numbers 
0  1  a -0.374751 
1  0  a 1.663334 
2  0  a -0.123599 
3  1  b -2.156204 
4  0  b 0.201493 
5  0  b 1.639512 
6  0  c -0.447271 
7  0  c 0.017204 
8  1  c -1.261621 

так что здесь происходит то, что с помощью вызова loc мы выбираем только те строки, которые возвращаются на ваш метод transform и они получают набор для 1 по желанию.

Не уверены, если это имеет значение много, но вы могли бы назвать unique, так что вы получите только заголовки строк без повторения, которые могут быть быстрее:

df.loc[df.groupby('letters')['numbers'].transform('idxmin').unique(), 'is_min']=1 
+0

Спасибо. Кажется, что это работает без повторных значений, а затем вызывает уникальный. df.loc [df.groupby ('letters') ['numbers']. idxmin(). values, 'is_min'] = 1 –

1

Я хотел бы установить «is_min» седловину к 1, если «числа» - это минимальное значение по столбцам «буквы».

, возможно, более интуитивный метод заключается в расчете минимумов на группу letters, а затем использовать группы-накрест .apply для назначения is_min:

def set_is_min(m): 
    df.loc[df.numbers == m, 'is_min'] = 1 
mins = df.groupby('letters').numbers.min().apply(set_is_min) 

В больших dataframes, этот метод на самом деле на 20% быстрее, чем с помощью преобразования:

# timeit with 100'000 rows 
# .apply on group minima 
100 loops, best of 3: 16.7 ms per loop 
# .transform 
10 loops, best of 3: 21.9 ms per loop 

Я провел некоторое more benchmarks различных методов использования применяются и преобразования.