我有一个有团体的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
,以便结果系列可以合并到原始数据框中吗?
答案 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))