1

我有一个数据框 df,它有两列:ID 和日期。它记录不同日期的 ID 事件。两个字段都不是唯一的,但行在组合中是唯一的(没有 ID 在同一日期有多个记录)。

我有以下函数来添加一个新列来确定,在给定的记录/日期,ID 是否(真/假)在任何未来的日期有另一条记录:

def f(df):
    count = pd.Series(np.arange(1, len(df)+1), index=df["date"])
    day = count.index.shift(0, freq="D")
    next18month = count.index.shift(3000, freq="D")
    result =  count.asof(next18month).fillna(0).values - count.asof(day).fillna(0).values
    if result[0] > 0:
        return pd.Series(1, df.index)
    else:
        return pd.Series(0, df.index)

然后我可以将该函数应用于我的数据框,按 ID 分组:

df["everagain"] = df.groupby("id").apply(f)

它不起作用。我相信这result[0]是错误的。它在第一次出现 ID 时起作用(它计算第二次,触发真正的返回),但如果给定 id 有第二条记录,并且没有第三条记录,它仍然在第二条记录。有人可以帮助正确的符号吗?

(注意:考虑到我的数据集,3000 天足以算作永远)。

例如,如果 df 看起来像:

   |  ID  |  Date
0  |  A   |  2010-01-01
1  |  A   |  2010-02-01
2  |  A   |  2010-02-15
3  |  B   |  2010-01-01
4  |  C   |  2010-02-01
5  |  C   |  2010-02-15

然后输出有望如下所示:

   |  ID  |  Date        | everagain
0  |  A   |  2010-01-01  | 1
1  |  A   |  2010-02-01  | 1
2  |  A   |  2010-02-15  | 0
3  |  B   |  2010-01-01  | 0
4  |  C   |  2010-02-01  | 1
5  |  C   |  2010-02-15  | 0
4

1 回答 1

1

我原本以为我可以使用.groupby("ID").last(),但不能完全让它工作。(当然,我们可以用 来做到这一点transform,但感觉火力太大了。)

但是,如果您的数据按顺序排列date并具有连续的 ID,您可以简单地比较是否ID等于下一个ID。例如:

>>> df = df.sort(["ID", "Date"])
>>> df
  ID                Date
0  A 2010-01-01 00:00:00
1  A 2010-02-01 00:00:00
2  A 2010-02-15 00:00:00
3  B 2010-01-01 00:00:00
4  C 2010-02-01 00:00:00
5  C 2010-02-15 00:00:00
>>> df["everagain"] = df["ID"] == df["ID"].shift(-1)
>>> df
  ID                Date everagain
0  A 2010-01-01 00:00:00      True
1  A 2010-02-01 00:00:00      True
2  A 2010-02-15 00:00:00     False
3  B 2010-01-01 00:00:00     False
4  C 2010-02-01 00:00:00      True
5  C 2010-02-15 00:00:00     False

如果您想要 1 和 0 而不是True and False,您可以使用(df["ID"] == df["ID"].shift(-1))*1)or(df["ID"] == df["ID"].shift(-1)).astype(int)来转换它们。

于 2013-09-24T01:35:51.597 回答