2015-03-09 3 views
3

У меня есть рамка данных pandas со столбцами (среди прочих) user_id и start_time. Я хочу эффективно и легко найти все строки, связанные с максимальным размером пользователя start_time.Эффективный максимальный выбор в рамке данных панд с условием выбора

Например, если это были мои данные:

user_id start_time A B C 
1   37   a b c 
1   45   d e f 
1   45   g h i 
2   58   j k l 
2   17   m n o 
2   58   p q r 
3   2   s t u 

, то я бы ожидать, чтобы найти

user_id start_time A B C 
1   45   d e f 
1   45   g h i 
2   58   j k l 
2   58   p q r 
3   2   s t u 

Я придумываю решения немного как Conditional selection of data in a pandas DataFrame, но находит user_id с последним start time, а не выбор таблицы для каждого пользователя max start_time.

Конечно, это легко, если я повторил DataFrame вручную, но это неэффективно.

Спасибо за любые указатели.

Для удобства будущих читателей, порождают dataframe таким образом:

columns = ['user_id', 'start_time', 'A', 'B', 'C'] 
LoL = [ 
    [1, 37, 'a', 'b', 'c'], 
    [1, 45, 'd', 'e', 'f'], 
    [1, 45, 'g', 'h', 'i'], 
    [2, 58, 'j', 'k', 'l'], 
    [2, 17, 'm', 'n', 'o'], 
    [2, 58, 'p', 'q', 'r'], 
    [3, 2, 's', 't', 'u']] 
pd.DataFrame = (LoL, columns=columns) 
+0

Мне интересно знать, как GroupBy() и слияния() подход будет выполнять на большой рамке против других ответов ниже. Не могли бы вы попробовать? g = df.groupby ('user_id', as_index = False) ['start_time']. max() df.merge (g) –

ответ

2

Вы можете GroupBy столбец user_id, а затем вызвать apply и передать лямбда, который фильтрует результаты, в которых время начала равно максимальное значение , мы хотим создать из этого булевский индекс. Затем мы можем назвать reset_index, но из-за способом GroupBy отфильтровал мы получим сообщение об ошибке с дублированными столбцами, поэтому мы должны отбросить этот дубликат колонки:

In [66]: 

gp = df.groupby('user_id') 
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()]).reset_index(drop=True) 

Out[66]: 
    user_id start_time A B C 
0  1   45 d e f 
1  1   45 g g i 
2  2   58 j k l 
3  2   58 p q r 
4  3   2 s t u 

если мы не называем reset_index вы получите дублированные значения:

In [67]: 

gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()]) 
Out[67]: 
      user_id start_time A B C 
user_id         
1  1  1   45 d e f 
     2  1   45 g g i 
2  3  2   58 j k l 
     5  2   58 p q r 
3  6  3   2 s t u 

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

In [68]: 

gp.apply(lambda x: x['start_time'] == x['start_time'].max()) 
Out[68]: 
user_id 
1  0 False 
     1  True 
     2  True 
2  3  True 
     4 False 
     5  True 
3  6  True 
Name: start_time, dtype: bool 
+0

В гораздо большем наборе данных это выполняется в 790 мс по сравнению с 1345 мс для ajcr и Решения Primer. (Все они кажутся мне верными). – jma

1

В качестве альтернативы вы можете сделать это:

df[df.start_time == df.groupby('user_id')['start_time'].transform(max)] 

Что дает:

user_id start_time A B C 
1  1   45 d e f 
2  1   45 g h i 
3  2   58 j k l 
5  2   58 p q r 
6  3   2 s t u