2017-02-15 1 views
3

У меня есть dataframe с целым индексом, session_id, событием и time_stamp который выглядит следующим образом:Панда разница метки времени в GroupBy преобразования

In [41]: df = pd.DataFrame(data={'session_id': np.sort(np.random.choice(np.arange(3), 11)), 'event': np.random.choice(['A', 'B', 'C', 'D'], 11), 'time_stamp': pd.date_range 
    ...: ('1/1/2017', periods=11, freq='S')}).reset_index(drop=True) 

In [42]: df 
Out[42]: 
    event session_id   time_stamp 
0  B   0 2017-01-01 00:00:00 
1  C   0 2017-01-01 00:00:01 
2  D   0 2017-01-01 00:00:02 
3  B   1 2017-01-01 00:00:03 
4  B   1 2017-01-01 00:00:04 
5  D   2 2017-01-01 00:00:05 
6  B   2 2017-01-01 00:00:06 
7  A   2 2017-01-01 00:00:07 
8  B   2 2017-01-01 00:00:08 
9  B   2 2017-01-01 00:00:09 
10  A   2 2017-01-01 00:00:10 

Я хочу, чтобы вычислить длину сеанса, используя groupby по и lambda функции, но я хочу вернуть объект серии, проиндексированный так же, как и исходный фреймворк данных, поэтому я могу добавить его как столбец. Это должно быть возможным с groupby.transform, как это, но он возвращает странное «не может преобразовать объект в NumPy даты и времени» Ошибка:

In [44]: df.groupby('session_id')['time_stamp'].transform(lambda x: x.max() - x.min()) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-44-c67ed1d4a90e> in <module>() 
----> 1 df.groupby('session_id')['time_stamp'].transform(lambda x: x.max() - x.min()) 

/Users/hendele/anaconda2/lib/python2.7/site-packages/pandas/core/groupby.pyc in transform(self, func, *args, **kwargs) 
    2843 
    2844    indexer = self._get_index(name) 
-> 2845    result[indexer] = res 
    2846 
    2847   result = _possibly_downcast_to_dtype(result, dtype) 

ValueError: Could not convert object to NumPy datetime 

Я думал, что я использовал это неправильно, но когда вы используете groupby.agg, это работает!

In [43]: df.groupby('session_id')['time_stamp'].agg(lambda x: x.max() - x.min()) 
Out[43]: 
session_id 
0 00:00:02 
1 00:00:01 
2 00:00:05 
Name: time_stamp, dtype: timedelta64[ns] 

Не могли бы вы объяснить, является ли это ошибкой или нет, а если нет, то что я делаю неправильно? Благодаря!

p.s. не хотел использовать индекс timestamp, потому что у меня могут быть повторяющиеся временные метки в реальных данных.

+0

PR был объединен, а исправление должно быть в '0.20.0'. –

ответ

1

Почему agg работает, но transform не удается?

Разница между этими двумя поведениями заключается в том, что операция transform() должна возвращать индексированные значения. Чтобы облегчить это, transform начинается с копии оригинальной серии. Затем, после вычисления для каждой группы, задает соответствующие элементы скопированной серии, равные результату. В этот момент происходит сравнение типов и обнаруживается, что timedelta не может быть использован для ввода в datetime. agg() не выполняет этот шаг, поэтому не проверяет тип проверки.

работа вокруг:

Этот анализ предполагает работу вокруг. Если результат transform равен datetime, он будет успешным. Таким образом, чтобы работать вокруг:

base_time = df['time_stamp'][0] 
df.groupby('session_id')['time_stamp'].transform(
    lambda x: x.max() - x.min() + base_time) - base_time 

Является ли это ошибка?

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

Update:

Я представил bug и pull request этого вопроса.

Смежные вопросы