从组开始添加每行计算时间差的列?

时间:2014-02-10 20:51:31

标签: python pandas

(新手到python和pandas)

我有一个15到2000万行的数据集,每行是一个时间索引观察“用户”的时间,我需要分析每个用户的每日访问模式,归一化第一次访问。所以,我希望用X轴“第一次访问后的天数”和Y轴“这个用户在这一天的访问”进行绘图,即,我需要得到一个由timedelta索引的系列,并且值为在那个以三角洲结束的时期访问[0:1,3:5,4:2,6:8]但是我很早就被卡住了......

我从这样的事情开始:

rng = pd.to_datetime(['2000-01-01 08:00', '2000-01-02 08:00',
                  '2000-01-01 08:15', '2000-01-02 18:00',
                  '2000-01-02 17:00', '2000-03-01 08:00',
                  '2000-03-01 08:20','2000-01-02 18:00'])
uid=Series(['u1','u2','u1','u2','u1','u2','u2','u3'])
misc=Series(['','x1','A123','1.23','','','','u3'])
df = DataFrame({'uid':uid,'misc':misc,'ts':rng})
df=df.set_index(df.ts)

grouped = df.groupby('uid')
firstseen = grouped.first()

ts值对于每个uid都是唯一的,但可以重复(可以同时看到两个uid,但只能看到uiddf['sinceseen'] = df.ts - firstseen.ts[df.uid] ... ValueError: cannot reindex from a duplicate axis 曾经在任何一个时间戳)

第一步是(我认为)向DataFrame添加一个新列,为每个观察显示timedelta返回到该用户的第一个观察。但是,我很难在DataFrame中获取该列。我试过的最简单的事情给了我一个模糊的新手错误信息:

def f(row):
    return row.ts - firstseen.ts[row.uid]
df['sinceseen'] = Series([{idx:f(row)} for idx, row in df.iterrows()], dtype=timedelta)

所以我尝试了一种暴力方法:

df

在此次尝试中,sinceseen获得了NaN,但全部为float并显示type(df.sinceseen[0])的{​​{1}}类型 - 但是,如果我只是打印系列(在iPython中)它会生成一个很好的timedeltas列表。

我正在通过“Python for Data Analysis”来回工作,似乎apply()应该可以工作,但是

def fg(ugroup):
    ugroup['sinceseen'] = ugroup.index - ugroup.index.min()
    return ugroup

df = df.groupby('uid').apply(fg)

在“TypeError”上给我一个ugroup.index - ugroup.index.min(,即使两个操作数都是Timestamp

所以,我正在肆无忌惮 - 有人能指出我以“熊猫”的方式进入Ineed的数据结构吗?

1 个答案:

答案 0 :(得分:3)

这有助于您入门吗?

>>> df = DataFrame({'uid':uid,'misc':misc,'ts':rng})
>>> df = df.sort(["uid", "ts"])
>>> df["since_seen"] = df.groupby("uid")["ts"].apply(lambda x: x - x.iloc[0])
>>> df
   misc                  ts uid        since_seen
0       2000-01-01 08:00:00  u1  0 days, 00:00:00
2  A123 2000-01-01 08:15:00  u1  0 days, 00:15:00
4       2000-01-02 17:00:00  u1  1 days, 09:00:00
1    x1 2000-01-02 08:00:00  u2  0 days, 00:00:00
3  1.23 2000-01-02 18:00:00  u2  0 days, 10:00:00
5       2000-03-01 08:00:00  u2 59 days, 00:00:00
6       2000-03-01 08:20:00  u2 59 days, 00:20:00
7    u3 2000-01-02 18:00:00  u3  0 days, 00:00:00

[8 rows x 4 columns]