Pandas apply обычно не рекомендуется использовать. У меня есть ситуация, когда мне интересно, есть ли более эффективные альтернативы варианту применения.
import numpy as np
import pandas as pd
df = pd.DataFrame({'year': [1990,1990,1990,1992,1992,1992,1992,1993,1993,1993],
'item': list('abcdefghij'),
'value': [100,200,300,400,500,600,700,800,900,990]})
df
Я хотел бы получить 2 лучших значения за каждый год.
df.groupby('year')['value'].apply(lambda x: x.nlargest(2)).reset_index()
Есть ли альтернатива этому? Что угодно, будь то более длинные строки кодов или что-то еще!
sort_values
что делать с tail
df.sort_values('value').groupby('year').tail(2) # when need continue position
Out[199]:
year item value
1 1990 b 200
2 1990 c 300
5 1992 f 600
6 1992 g 700
8 1993 i 900
9 1993 j 990
Или
df.sort_values('value').groupby('year',as_index=False).nth([-2,-1])#more flexible you can pick 1,-1
Out[202]:
year item value
1 1990 b 200
2 1990 c 300
5 1992 f 600
6 1992 g 700
8 1993 i 900
9 1993 j 990
Сроки
%timeit df.sort_values('value').groupby('year').tail(2)
1000 loops, best of 3: 894 µs per loop
%timeit df.groupby('year')['value'].apply(lambda x: x.nlargest(2)).reset_index()
100 loops, best of 3: 2.76 ms per loop
@Yuca вывод отличается, примените, не включайте столбец элемента, также измените порядок столбцов
согласен, просто интересно, является ли это более эффективным, чем использование apply, поскольку это также то, о чем спрашивал ОП. Не говорю, что с ответом что-то не так, просто любопытно
@Yuca, проверь время :-)
Когда у нас есть NaN
import numpy as np
import pandas as pd
df = pd.DataFrame({'item': list('abcdefghijk'),
'year': [1990,1990,1990,1992,1992,1992,1992,1993,1993,1993,1993],
'value':[10 , 11 ,12 ,20 ,21 ,22 ,23 ,30 ,31 ,32 ,np.nan]})
print(df)
item year value
0 a 1990 10.0
1 b 1990 11.0
2 c 1990 12.0
3 d 1992 20.0
4 e 1992 21.0
5 f 1992 22.0
6 g 1992 23.0
7 h 1993 30.0
8 i 1993 31.0
9 j 1993 32.0
10 k 1993 NaN
top2 = df.groupby('year')['value'].apply(lambda x: x.nlargest(2)).reset_index(level=0)
print(df.loc[top2.index])
# time: 2.96ms
item year value
2 c 1990 12.0
1 b 1990 11.0
6 g 1992 23.0
5 f 1992 22.0
9 j 1993 32.0
8 i 1993 31.0
print(df.dropna(subset=['value']).sort_values('value').groupby('year').tail(2))
# time: 2.01ms
item year value
1 b 1990 11.0
2 c 1990 12.0
5 f 1992 22.0
6 g 1992 23.0
8 i 1993 31.0
9 j 1993 32.0
есть ли у нас уверенность, что этот подход более эффективен, чем
apply
?