pandas:创建一个从1到每组长度的列

时间:2018-05-31 23:35:36

标签: python python-3.x pandas

我有一个有团体的df。对于每个组,我想形成一个新列,其中包含从1到该组中行数的整数。以下尝试不起作用,因为它创建一行具有多个列而不是一列具有多个行。为什么会这样?

df = pd.DataFrame(data = {"a": np.arange(5), "b": np.arange(5)[::-1], "id": [1,1,1,2,2]}).set_index("id")
df["c"] = df.groupby("id").apply(lambda x: np.arange(1, len(x)+1))

或者,如果我尝试返回Series对象,如:

df["c"] = df.groupby("id").apply(lambda x: pd.Series(data = np.arange(1, len(x)+1)))

这引发了一个异常,说索引是不兼容的(这是有道理的,因为返回的Series现在有一个MultiIndex

更新:让我更一般地提出这个问题:如何在数据帧上groupby返回与数据帧具有相同索引的Series,以便结果系列可以合并到原始数据框中吗?

2 个答案:

答案 0 :(得分:3)

df["c"] = 1 + df.groupby("id").cumcount()

您的解决方案不起作用的原因是groupby& agg尝试为每个创建结果,而不是为每个创建结果。因此,以下内容为每个组创建一个数字列表

df.groupby("id").apply(lambda x: np.arange(1, len(x)+1))

发表评论:要the numbers in reverse groupby - sort - cumcount,您可以rolling / resample

对于更一般的需求,您可能需要查看groupby + transform个功能。

  

让我让这个问题更加笼统:怎么做groupby   在数据帧上返回与数据帧具有相同索引的Series   以便生成的系列可以合并到原始系列中   数据帧?

您需要df["c"] = df.groupby("id")["a"].transform(lambda x: np.arange(1, len(x)+1)) 但是对于像这样的累积操作案例它不起作用。实际上它可以,如@Alex回答中所示

{{1}}

答案 1 :(得分:1)

这是一种相当普遍的正确方法:

df["c"] = df.groupby("id")["a"].transform(lambda x: np.arange(1, len(x)+1))