4

我有一个带有整数索引、session_id、事件和时间戳的数据框,如下所示:

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

我想使用groupbyby 和一个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]

你能否解释一下这是否是一个错误,如果不是,我做错了什么?谢谢!

ps 不想使用时间戳索引,因为我可能在实际数据中有重复的时间戳。

4

1 回答 1

1

为什么agg工作但transform失败?

这两种行为的区别在于transform()操作需要返回一个like-indexed。为了促进这一点,transform从原始系列的副本开始。然后,在每个组的计算之后,将复制系列的适当元素设置为等于结果。此时 is 进行类型比较,并发现timedelta不能强制转换为 a datetimeagg()不执行此步骤,因此不会使类型检查失败。

解决方法:

该分析建议解决方法。如果 的结果transform是 a datetime,它将成功。所以要解决:

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

这是一个错误吗?

我认为这是一个错误,我计划在早上提交一个问题。我将在这里更新问题链接。

更新:

我已经为此问题提交了一个错误和一个拉取请求。

于 2017-02-16T06:10:30.157 回答